From fd5baead857c514d1f2e8bb88ee0f5e0031acd9b Mon Sep 17 00:00:00 2001 From: Stanislav Komanec Date: Wed, 11 Feb 2015 13:25:07 +0100 Subject: [PATCH 001/489] canceling XHR request using promises fixed --- src/ngResource/resource.js | 4 +++- test/ngResource/resourceSpec.js | 34 ++++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/ngResource/resource.js b/src/ngResource/resource.js index e916de8351dd..84340b816b4f 100644 --- a/src/ngResource/resource.js +++ b/src/ngResource/resource.js @@ -560,8 +560,10 @@ angular.module('ngResource', ['ng']). undefined; forEach(action, function(value, key) { - if (key != 'params' && key != 'isArray' && key != 'interceptor') { + if (key != 'params' && key != 'isArray' && key != 'interceptor' && key != 'timeout') { httpConfig[key] = copy(value); + } else if (key == 'timeout') { + httpConfig[key] = value; } }); diff --git a/test/ngResource/resourceSpec.js b/test/ngResource/resourceSpec.js index ba72525e6de9..813a75659df7 100644 --- a/test/ngResource/resourceSpec.js +++ b/test/ngResource/resourceSpec.js @@ -1295,7 +1295,7 @@ describe("resource", function() { }); describe('resource', function() { - var $httpBackend, $resource; + var $httpBackend, $resource, $q; beforeEach(module(function($exceptionHandlerProvider) { $exceptionHandlerProvider.mode('log'); @@ -1306,6 +1306,7 @@ describe('resource', function() { beforeEach(inject(function($injector) { $httpBackend = $injector.get('$httpBackend'); $resource = $injector.get('$resource'); + $q = $injector.get('$q'); })); @@ -1343,5 +1344,36 @@ describe('resource', function() { ); }); + it('If timeout promise is resolved, cancel the request', function() { + var canceler = $q.defer(); + + $httpBackend.when('GET', '/CreditCard').respond({data: '123'}); + + var CreditCard = $resource('/CreditCard', {}, { + query: { + method: 'GET', + timeout: canceler.promise + } + }); + + CreditCard.query(); + + canceler.resolve(); + expect(function() { $httpBackend.flush();}).toThrow(new Error("No pending request to flush !")); + + canceler = $q.defer(); + CreditCard = $resource('/CreditCard', {}, { + query: { + method: 'GET', + timeout: canceler.promise + } + }); + + CreditCard.query(); + expect(function() { $httpBackend.flush();}).not.toThrow(new Error("No pending request to flush !")); + + + }); + }); From 3b62010b28fea1ec639df0c637eeb679d4508353 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Thu, 12 Feb 2015 11:59:15 +0000 Subject: [PATCH 002/489] docs(FAQ): update the zipped file size --- docs/content/misc/faq.ngdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/misc/faq.ngdoc b/docs/content/misc/faq.ngdoc index 2a3d85f0e5cf..a6028333b9ab 100644 --- a/docs/content/misc/faq.ngdoc +++ b/docs/content/misc/faq.ngdoc @@ -67,7 +67,7 @@ illustration, we typically build snappy apps with hundreds or thousands of activ ### How big is the angular.js file that I need to include? -The size of the file is < 36KB compressed and minified. +The size of the file is ~50KB compressed and minified. ### Can I use the open-source Closure Library with Angular? From 6ac595998349063bf74c46bd67a838a20e8fd7c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Wed, 7 Jan 2015 18:16:15 -0500 Subject: [PATCH 003/489] feat(ngMessages): provide support for dynamic message resolution Prior to this fix it was impossible to apply a binding to a the ngMessage directive to represent the name of the error. It was also not possible to use ngRepeat or any other structural directive to dynamically update the list of messages. This feature patch ensures that both ngMessages can render expressions and automatically update when any dynamic message data changes. BREAKING CHANGE: The `ngMessagesInclude` attribute is now its own directive and that must be placed as a **child** element within the element with the ngMessages directive. (Keep in mind that the former behaviour of the ngMessageInclude attribute was that all **included** ngMessage template code was placed at the **bottom** of the element containing the ngMessages directive; therefore to make this behave in the same way, place the element containing the ngMessagesInclude directive at the end of the container containing the ngMessages directive). ```html
Your message is required
Your message is required
``` Closes #10036 Closes #9338 --- src/ngMessages/messages.js | 498 ++++++++++++++++++++++++-------- test/ngMessages/messagesSpec.js | 287 ++++++++++++++---- 2 files changed, 594 insertions(+), 191 deletions(-) diff --git a/src/ngMessages/messages.js b/src/ngMessages/messages.js index 04b468fe5a4a..5fb585b98d58 100644 --- a/src/ngMessages/messages.js +++ b/src/ngMessages/messages.js @@ -1,5 +1,13 @@ 'use strict'; +/* jshint ignore:start */ +// this code is in the core, but not in angular-messages.js +var isArray = angular.isArray; +var forEach = angular.forEach; +var isString = angular.isString; +var jqLite = angular.element; +/* jshint ignore:end */ + /** * @ngdoc module * @name ngMessages @@ -12,8 +20,8 @@ * `ngMessage` directives are designed to handle the complexity, inheritance and priority * sequencing based on the order of how the messages are defined in the template. * - * Currently, the ngMessages module only contains the code for the `ngMessages` - * and `ngMessage` directives. + * Currently, the ngMessages module only contains the code for the `ngMessages`, `ngMessagesInclude` + * `ngMessage` and `ngMessageExp` directives. * * # Usage * The `ngMessages` directive listens on a key/value collection which is set on the ngMessages attribute. @@ -26,7 +34,9 @@ * *
*
You did not enter a field
- *
The value entered is too short
+ *
+ * Your email must be between 5 and 100 characters long + *
*
* * ``` @@ -52,7 +62,11 @@ * ngMessages directive to make this happen. * * ```html + * *
...
+ * + * + * ... * ``` * * ## Reusing and Overriding Messages @@ -65,7 +79,10 @@ *
This field is required
*
This field is too short
* - *
+ * + *
+ *
+ *
* ``` * * However, including generic messages may not be useful enough to match all input fields, therefore, @@ -87,12 +104,17 @@ * minlength="5" * required /> * - *
+ * + *
* *
You did not enter your email address
* * *
Your email address is invalid
+ * + * + *
*
* * ``` @@ -102,10 +124,65 @@ * email addresses, date fields, autocomplete inputs, etc...), specialized error messages can be applied * while more generic messages can be used to handle other, more general input errors. * + * ## Dynamic Messaging + * ngMessages also supports using expressions to dynamically change key values. Using arrays and + * repeaters to list messages is also supported. This means that the code below will be able to + * fully adapt itself and display the appropriate message when any of the expression data changes: + * + * ```html + *
+ * + * + *
+ *
You did not enter your email address
+ *
+ * + *
{{ errorMessage.text }}
+ *
+ *
+ *
+ * ``` + * + * The `errorMessage.type` expression can be a string value or it can be an array so + * that multiple errors can be associated with a single error message: + * + * ```html + * + *
+ *
You did not enter your email address
+ *
+ * Your email must be between 5 and 100 characters long + *
+ *
+ * ``` + * + * Feel free to use other structural directives such as ng-if and ng-switch to further control + * what messages are active and when. Be careful, if you place ng-message on the same element + * as these structural directives, Angular may not be able to determine if a message is active + * or not. Therefore it is best to place the ng-message on a child element of the structural + * directive. + * + * ```html + *
+ *
+ *
Please enter something
+ *
+ *
+ * ``` + * * ## Animations - * If the `ngAnimate` module is active within the application then both the `ngMessages` and - * `ngMessage` directives will trigger animations whenever any messages are added and removed - * from the DOM by the `ngMessages` directive. + * If the `ngAnimate` module is active within the application then the `ngMessages`, `ngMessage` and + * `ngMessageExp` directives will trigger animations whenever any messages are added and removed from + * the DOM by the `ngMessages` directive. * * Whenever the `ngMessages` directive contains one or more visible messages then the `.ng-active` CSS * class will be added to the element. The `.ng-inactive` CSS class will be applied when there are no @@ -171,7 +248,7 @@ angular.module('ngMessages', []) * messages use the `ngMessage` directive and will be inserted/removed from the page depending * on if they're present within the key/value object. By default, only one message will be displayed * at a time and this depends on the prioritization of the messages within the template. (This can - * be changed by using the ng-messages-multiple on the directive container.) + * be changed by using the `ng-messages-multiple` or `multiple` attribute on the directive container.) * * A remote template can also be used to promote message reusability and messages can also be * overridden. @@ -182,23 +259,22 @@ angular.module('ngMessages', []) * ```html * * - * ... - * ... - * ... + * ... + * ... + * ... * * * * - * ... - * ... - * ... + * ... + * ... + * ... * * ``` * * @param {string} ngMessages an angular expression evaluating to a key/value object * (this is typically the $error object on an ngModel instance). * @param {string=} ngMessagesMultiple|multiple when set, all messages will be displayed with true - * @param {string=} ngMessagesInclude|include when set, the specified template will be included into the ng-messages container * * @example * * */ - .directive('ngMessages', ['$compile', '$animate', '$templateRequest', - function($compile, $animate, $templateRequest) { - var ACTIVE_CLASS = 'ng-active'; - var INACTIVE_CLASS = 'ng-inactive'; + .directive('ngMessages', ['$animate', function($animate) { + var ACTIVE_CLASS = 'ng-active'; + var INACTIVE_CLASS = 'ng-inactive'; - return { - restrict: 'AE', - controller: function() { - this.$renderNgMessageClasses = angular.noop; - - var messages = []; - this.registerMessage = function(index, message) { - for (var i = 0; i < messages.length; i++) { - if (messages[i].type == message.type) { - if (index != i) { - var temp = messages[index]; - messages[index] = messages[i]; - if (index < messages.length) { - messages[i] = temp; - } else { - messages.splice(0, i); //remove the old one (and shift left) - } - } - return; - } - } - messages.splice(index, 0, message); //add the new one (and shift right) - }; + return { + require: 'ngMessages', + restrict: 'AE', + controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) { + var ctrl = this; + var latestKey = 0; - this.renderMessages = function(values, multiple) { - values = values || {}; + var messages = this.messages = {}; + var renderLater, cachedCollection; - var found; - angular.forEach(messages, function(message) { - if ((!found || multiple) && truthyVal(values[message.type])) { - message.attach(); - found = true; - } else { - message.detach(); - } - }); + this.render = function(collection) { + collection = collection || {}; - this.renderElementClasses(found); + renderLater = false; + cachedCollection = collection; - function truthyVal(value) { - return value !== null && value !== false && value; - } - }; - }, - require: 'ngMessages', - link: function($scope, element, $attrs, ctrl) { - ctrl.renderElementClasses = function(bool) { - bool ? $animate.setClass(element, ACTIVE_CLASS, INACTIVE_CLASS) - : $animate.setClass(element, INACTIVE_CLASS, ACTIVE_CLASS); - }; + // this is true if the attribute is empty or if the attribute value is truthy + var multiple = isAttrTruthy($scope, $attrs.ngMessagesMultiple) || + isAttrTruthy($scope, $attrs.multiple); - //JavaScript treats empty strings as false, but ng-message-multiple by itself is an empty string - var multiple = angular.isString($attrs.ngMessagesMultiple) || - angular.isString($attrs.multiple); + var unmatchedMessages = []; + var matchedKeys = {}; + var messageItem = ctrl.head; + var messageFound = false; + var totalMessages = 0; - var cachedValues, watchAttr = $attrs.ngMessages || $attrs['for']; //for is a reserved keyword - $scope.$watchCollection(watchAttr, function(values) { - cachedValues = values; - ctrl.renderMessages(values, multiple); - }); + // we use != instead of !== to allow for both undefined and null values + while (messageItem != null) { + totalMessages++; + var messageCtrl = messageItem.message; - var tpl = $attrs.ngMessagesInclude || $attrs.include; - if (tpl) { - $templateRequest(tpl) - .then(function processTemplate(html) { - var after, container = angular.element('
').html(html); - angular.forEach(container.children(), function(elm) { - elm = angular.element(elm); - after ? after.after(elm) - : element.prepend(elm); //start of the container - after = elm; - $compile(elm)($scope); - }); - ctrl.renderMessages(cachedValues, multiple); - }); - } - } - }; - }]) + var messageUsed = false; + if (!messageFound) { + forEach(collection, function(value, key) { + if (!messageUsed && truthy(value) && messageCtrl.test(key)) { + // this is to prevent the same error name from showing up twice + if (matchedKeys[key]) return; + matchedKeys[key] = true; + + messageUsed = true; + messageCtrl.attach(); + } + }); + } + + if (messageUsed) { + // unless we want to display multiple messages then we should + // set a flag here to avoid displaying the next message in the list + messageFound = !multiple; + } else { + unmatchedMessages.push(messageCtrl); + } + + messageItem = messageItem.next; + } + + forEach(unmatchedMessages, function(messageCtrl) { + messageCtrl.detach(); + }); + unmatchedMessages.length !== totalMessages + ? $animate.setClass($element, ACTIVE_CLASS, INACTIVE_CLASS) + : $animate.setClass($element, INACTIVE_CLASS, ACTIVE_CLASS); + }; + + $scope.$watchCollection($attrs.ngMessages || $attrs['for'], ctrl.render); + + this.reRender = function() { + if (!renderLater) { + renderLater = true; + $scope.$evalAsync(function() { + if (renderLater) { + cachedCollection && ctrl.render(cachedCollection); + } + }); + } + }; + + this.register = function(comment, messageCtrl) { + var nextKey = latestKey.toString(); + messages[nextKey] = { + message: messageCtrl + }; + insertMessageNode($element[0], comment, nextKey); + comment.$$ngMessageNode = nextKey; + latestKey++; + + ctrl.reRender(); + }; + + this.deregister = function(comment) { + var key = comment.$$ngMessageNode; + delete comment.$$ngMessageNode; + removeMessageNode($element[0], comment, key); + delete messages[key]; + ctrl.reRender(); + }; + + function findPreviousMessage(parent, comment) { + var prevNode = comment; + var parentLookup = []; + while (prevNode && prevNode !== parent) { + var prevKey = prevNode.$$ngMessageNode; + if (prevKey && prevKey.length) { + return messages[prevKey]; + } + + // dive deeper into the DOM and examine its children for any ngMessage + // comments that may be in an element that appears deeper in the list + if (prevNode.childNodes.length && parentLookup.indexOf(prevNode) == -1) { + parentLookup.push(prevNode); + prevNode = prevNode.childNodes[prevNode.childNodes.length - 1]; + } else { + prevNode = prevNode.previousSibling || prevNode.parentNode; + } + } + } + + function insertMessageNode(parent, comment, key) { + var messageNode = messages[key]; + if (!ctrl.head) { + ctrl.head = messageNode; + } else { + var match = findPreviousMessage(parent, comment); + if (match) { + messageNode.next = match.next; + match.next = messageNode; + } else { + messageNode.next = ctrl.head; + ctrl.head = messageNode; + } + } + } + + function removeMessageNode(parent, comment, key) { + var messageNode = messages[key]; + + var match = findPreviousMessage(parent, comment); + if (match) { + match.next = messageNode.next; + } else { + ctrl.head = messageNode.next; + } + } + }] + }; + + function isAttrTruthy(scope, attr) { + return (isString(attr) && attr.length === 0) || //empty attribute + truthy(scope.$eval(attr)); + } + + function truthy(val) { + return isString(val) ? val.length : !!val; + } + }]) + + /** + * @ngdoc directive + * @name ngMessagesInclude + * @restrict AE + * @scope + * + * @description + * `ngMessagesInclude` is a directive with the purpose to import existing ngMessage template + * code from a remote template and place the downloaded template code into the exact spot + * that the ngMessagesInclude directive is placed within the ngMessages container. This allows + * for a series of pre-defined messages to be reused and also allows for the developer to + * determine what messages are overridden due to the placement of the ngMessagesInclude directive. + * + * @usage + * ```html + * + * + * ... + * + * + * + * + * ... + * + * ``` + * + * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`. + * + * @param {string} ngMessagesInclude|src a string value corresponding to the remote template. + */ + .directive('ngMessagesInclude', + ['$templateRequest', '$document', '$compile', function($templateRequest, $document, $compile) { + + return { + restrict: 'AE', + require: '^^ngMessages', + compile: function(element, attrs) { + var comment = jqLite($document[0].createComment(' ngMessagesInclude: ')); + element.after(comment); + + return function($scope, $element, attrs, ngMessagesCtrl) { + // we're removing this since we only need access to the newly + // created comment node as an anchor. + element.remove(); + + $templateRequest(attrs.ngMessagesInclude || attrs.src).then(function(html) { + var elements = jqLite('
').html(html).contents(); + var cursor = comment; + forEach(elements, function(elm) { + elm = jqLite(elm); + cursor.after(elm); + cursor = elm; + }); + $compile(elements)($scope); + }); + }; + } + }; + }]) /** * @ngdoc directive @@ -330,63 +541,96 @@ angular.module('ngMessages', []) * ```html * * - * ... - * ... - * ... + * ... + * ... + * ... * * * * - * ... - * ... - * ... + * ... + * ... + * ... * * ``` * * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`. * - * @param {string} ngMessage a string value corresponding to the message key. + * @param {expression} ngMessage|when a string value corresponding to the message key. + * @param {expression} ngMessageExp|whenExp an expression value corresponding to the message key. */ - .directive('ngMessage', ['$animate', function($animate) { - var COMMENT_NODE = 8; + .directive('ngMessage', ngMessageDirectiveFactory('AE')) + .directive('ngMessageExp', ngMessageDirectiveFactory('A')); + +function ngMessageDirectiveFactory(restrict) { + return ['$animate', function($animate) { return { - require: '^ngMessages', + restrict: 'AE', transclude: 'element', terminal: true, - restrict: 'AE', - link: function($scope, $element, $attrs, ngMessages, $transclude) { - var index, element; - - var commentNode = $element[0]; - var parentNode = commentNode.parentNode; - for (var i = 0, j = 0; i < parentNode.childNodes.length; i++) { - var node = parentNode.childNodes[i]; - if (node.nodeType == COMMENT_NODE && node.nodeValue.indexOf('ngMessage') >= 0) { - if (node === commentNode) { - index = j; - break; - } - j++; - } + require: '^^ngMessages', + link: function(scope, element, attrs, ngMessagesCtrl, $transclude) { + var commentNode = element[0]; + + var records; + var staticExp = attrs.ngMessage || attrs.when; + var dynamicExp = attrs.ngMessageExp || attrs.whenExp; + var assignRecords = function(items) { + records = items + ? (isArray(items) + ? items + : items.split(/[\s,]+/)) + : null; + ngMessagesCtrl.reRender(); + }; + + if (dynamicExp) { + assignRecords(scope.$eval(dynamicExp)); + scope.$watchCollection(dynamicExp, assignRecords); + } else { + assignRecords(staticExp); } - ngMessages.registerMessage(index, { - type: $attrs.ngMessage || $attrs.when, + var currentElement, messageCtrl; + ngMessagesCtrl.register(commentNode, messageCtrl = { + test: function(name) { + return contains(records, name); + }, attach: function() { - if (!element) { - $transclude($scope, function(clone) { - $animate.enter(clone, null, $element); - element = clone; + if (!currentElement) { + $transclude(scope, function(elm) { + $animate.enter(elm, null, element); + currentElement = elm; + + // in the event that the parent element is destroyed + // by any other structural directive then it's time + // to deregister the message from the controller + currentElement.on('$destroy', function() { + if (currentElement) { + ngMessagesCtrl.deregister(commentNode); + messageCtrl.detach(); + } + }); }); } }, detach: function() { - if (element) { - $animate.leave(element); - element = null; + if (currentElement) { + var elm = currentElement; + currentElement = null; + $animate.leave(elm); } } }); } }; - }]); + }]; + + function contains(collection, key) { + if (collection) { + return isArray(collection) + ? collection.indexOf(key) >= 0 + : collection.hasOwnProperty(key); + } + } +} diff --git a/test/ngMessages/messagesSpec.js b/test/ngMessages/messagesSpec.js index a0b39ddf8570..26215741c6bf 100644 --- a/test/ngMessages/messagesSpec.js +++ b/test/ngMessages/messagesSpec.js @@ -41,7 +41,40 @@ describe('ngMessages', function() { expect(element.text()).toContain('Message is set'); })); - it('should use the data attribute when an element directive is used', + it('should render the same message if multiple message keys match', inject(function($rootScope, $compile) { + element = $compile('
' + + '
Message is set
' + + '
')($rootScope); + $rootScope.$digest(); + + expect(element.text()).not.toContain('Message is set'); + + $rootScope.$apply(function() { + $rootScope.col = { one: true }; + }); + + expect(element.text()).toContain('Message is set'); + + $rootScope.$apply(function() { + $rootScope.col = { two: true, one: false }; + }); + + expect(element.text()).toContain('Message is set'); + + $rootScope.$apply(function() { + $rootScope.col = { three: true, two: false }; + }); + + expect(element.text()).toContain('Message is set'); + + $rootScope.$apply(function() { + $rootScope.col = { three: false }; + }); + + expect(element.text()).not.toContain('Message is set'); + })); + + it('should use the when attribute when an element directive is used', inject(function($rootScope, $compile) { element = $compile('' + @@ -58,6 +91,111 @@ describe('ngMessages', function() { expect(element.text()).toContain('Message is set'); })); + it('should render the same message if multiple message keys match based on the when attribute', inject(function($rootScope, $compile) { + element = $compile('' + + ' Message is set
' + + '')($rootScope); + $rootScope.$digest(); + + expect(element.text()).not.toContain('Message is set'); + + $rootScope.$apply(function() { + $rootScope.col = { one: true }; + }); + + expect(element.text()).toContain('Message is set'); + + $rootScope.$apply(function() { + $rootScope.col = { two: true, one: false }; + }); + + expect(element.text()).toContain('Message is set'); + + $rootScope.$apply(function() { + $rootScope.col = { three: true, two: false }; + }); + + expect(element.text()).toContain('Message is set'); + + $rootScope.$apply(function() { + $rootScope.col = { three: false }; + }); + + expect(element.text()).not.toContain('Message is set'); + })); + + it('should allow a dynamic expression to be set when ng-message-exp is used', + inject(function($rootScope, $compile) { + + element = $compile('
' + + '
Message is crazy
' + + '
')($rootScope); + $rootScope.$digest(); + + expect(element.text()).not.toContain('Message is crazy'); + + $rootScope.$apply(function() { + $rootScope.variable = 'error'; + $rootScope.col = { error: true }; + }); + + expect(element.text()).toContain('Message is crazy'); + + $rootScope.$apply(function() { + $rootScope.col = { error: false, failure: true }; + }); + + expect(element.text()).not.toContain('Message is crazy'); + + $rootScope.$apply(function() { + $rootScope.variable = ['failure']; + }); + + expect(element.text()).toContain('Message is crazy'); + + $rootScope.$apply(function() { + $rootScope.variable = null; + }); + + expect(element.text()).not.toContain('Message is crazy'); + })); + + it('should allow a dynamic expression to be set when the when-exp attribute is used', + inject(function($rootScope, $compile) { + + element = $compile('' + + ' Message is crazy' + + '')($rootScope); + $rootScope.$digest(); + + expect(element.text()).not.toContain('Message is crazy'); + + $rootScope.$apply(function() { + $rootScope.variable = 'error, failure'; + $rootScope.col = { error: true }; + }); + + expect(element.text()).toContain('Message is crazy'); + + $rootScope.$apply(function() { + $rootScope.col = { error: false, failure: true }; + }); + + expect(element.text()).toContain('Message is crazy'); + + $rootScope.$apply(function() { + $rootScope.variable = []; + }); + + expect(element.text()).not.toContain('Message is crazy'); + + $rootScope.$apply(function() { + $rootScope.variable = null; + }); + + expect(element.text()).not.toContain('Message is crazy'); + })); + they('should render empty when $prop is used as a collection value', { 'null': null, 'false': false, @@ -189,6 +327,65 @@ describe('ngMessages', function() { expect(element.hasClass('ng-inactive')).toBe(false); })); + it('should automatically re-render the messages when other directives dynmically change them', + inject(function($rootScope, $compile) { + + element = $compile('
' + + '
Enter something
' + + '
' + + '
{{ item.text }}
' + + '
' + + '
')($rootScope); + + $rootScope.$apply(function() { + $rootScope.col = {}; + $rootScope.items = [ + { text: 'Your age is incorrect', name: 'age' }, + { text: 'You\'re too tall man!', name: 'height' }, + { text: 'Your hair is too long', name: 'hair' } + ]; + }); + + expect(messageChildren().length).toBe(0); + expect(trim(element.text())).toEqual(""); + + $rootScope.$apply(function() { + $rootScope.col = { hair: true }; + }); + + expect(messageChildren().length).toBe(1); + expect(trim(element.text())).toEqual("Your hair is too long"); + + $rootScope.$apply(function() { + $rootScope.col = { age: true, hair: true}; + }); + + expect(messageChildren().length).toBe(1); + expect(trim(element.text())).toEqual("Your age is incorrect"); + + $rootScope.$apply(function() { + // remove the age! + $rootScope.items.shift(); + }); + + expect(messageChildren().length).toBe(1); + expect(trim(element.text())).toEqual("Your hair is too long"); + + $rootScope.$apply(function() { + // remove the hair! + $rootScope.items.length = 0; + $rootScope.col.primary = true; + }); + + expect(messageChildren().length).toBe(1); + expect(trim(element.text())).toEqual("Enter something"); + + function messageChildren() { + return element[0].querySelectorAll('[ng-message], [ng-message-exp]'); + } + })); + + it('should render animations when the active/inactive classes are added/removed', function() { module('ngAnimate'); module('ngAnimateMock'); @@ -219,10 +416,12 @@ describe('ngMessages', function() { describe('when including templates', function() { they('should load a remote template using $prop', - {'
': - '
', - '': - ''}, + {'
': '
' + + '
' + + '
', + '': '' + + '' + + ''}, function(html) { inject(function($compile, $rootScope, $templateCache) { $templateCache.put('abc.html', '
A
' + @@ -259,7 +458,7 @@ describe('ngMessages', function() { expect($templateCache.get('tpl')).toBeUndefined(); - element = $compile('
')($rootScope); + element = $compile('
')($rootScope); $rootScope.$digest(); $httpBackend.flush(); @@ -270,9 +469,11 @@ describe('ngMessages', function() { it('should re-render the messages after download without an extra digest', inject(function($rootScope, $compile, $httpBackend) { - $httpBackend.expect('GET', 'my-messages').respond(201,'
You did not enter a value
'); + $httpBackend.expect('GET', 'my-messages').respond(201, + '
You did not enter a value
'); - element = $compile('
' + + element = $compile('
' + + '
' + '
Your value is that of failure
' + '
')($rootScope); @@ -287,20 +488,22 @@ describe('ngMessages', function() { expect(trim(element.text())).toEqual("Your value is that of failure"); $httpBackend.flush(); + $rootScope.$digest(); expect(element.children().length).toBe(1); expect(trim(element.text())).toEqual("You did not enter a value"); })); - it('should allow for overriding the remote template messages within the element', + it('should allow for overriding the remote template messages within the element depending on where the remote template is placed', inject(function($compile, $rootScope, $templateCache) { $templateCache.put('abc.html', '
A
' + '
B
' + '
C
'); - element = $compile('
' + + element = $compile('
' + '
AAA
' + + '
' + '
CCC
' + '
')($rootScope); @@ -332,50 +535,7 @@ describe('ngMessages', function() { }); expect(element.children().length).toBe(1); - expect(trim(element.text())).toEqual("CCC"); - })); - - it('should retain the order of the remote template\'s messages when overriding within the element', - inject(function($compile, $rootScope, $templateCache) { - - $templateCache.put('abc.html', '
C
' + - '
A
' + - '
B
'); - - element = $compile('
' + - '
AAA
' + - '
CCC
' + - '
')($rootScope); - - $rootScope.$apply(function() { - $rootScope.data = { - 'a': 1, - 'b': 2, - 'c': 3 - }; - }); - - expect(element.children().length).toBe(1); - expect(trim(element.text())).toEqual("CCC"); - - $rootScope.$apply(function() { - $rootScope.data = { - 'a': 1, - 'b': 2 - }; - }); - - expect(element.children().length).toBe(1); - expect(trim(element.text())).toEqual("AAA"); - - $rootScope.$apply(function() { - $rootScope.data = { - 'b': 3 - }; - }); - - expect(element.children().length).toBe(1); - expect(trim(element.text())).toEqual("B"); + expect(trim(element.text())).toEqual("C"); })); }); @@ -412,9 +572,9 @@ describe('ngMessages', function() { '
Y
' + '
Z
'); - element = $compile('
')($rootScope); + element = $compile('
' + + '
' + + '
')($rootScope); $rootScope.$apply(function() { $rootScope.data = { @@ -442,11 +602,10 @@ describe('ngMessages', function() { '
Y
' + '
Z
'); - element = $compile('
' + - '
YYY
' + - '
ZZZ
' + + element = $compile('
' + + '
YYY
' + + '
ZZZ
' + + '
' + '
')($rootScope); $rootScope.$apply(function() { @@ -458,14 +617,14 @@ describe('ngMessages', function() { }); expect(element.children().length).toBe(2); - expect(s(element.text())).toEqual("XZZZ"); + expect(s(element.text())).toEqual("ZZZX"); $rootScope.$apply(function() { $rootScope.data.y = {}; }); expect(element.children().length).toBe(3); - expect(s(element.text())).toEqual("XYYYZZZ"); + expect(s(element.text())).toEqual("YYYZZZX"); })); }); }); From 9ca20641432f0d79d3d6cf7ec9d4c2574dc9bae6 Mon Sep 17 00:00:00 2001 From: Julie Ralph Date: Wed, 11 Feb 2015 17:28:57 -0800 Subject: [PATCH 004/489] chore(ci): update to use the latest sauce connect (4.3 to 4.3.6) --- lib/saucelabs/start_tunnel.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/saucelabs/start_tunnel.sh b/lib/saucelabs/start_tunnel.sh index dcaa79788226..b79b22bc5126 100755 --- a/lib/saucelabs/start_tunnel.sh +++ b/lib/saucelabs/start_tunnel.sh @@ -12,9 +12,9 @@ set -e # before_script: # - curl https://gist.github.com/santiycr/5139565/raw/sauce_connect_setup.sh | bash -CONNECT_URL="https://saucelabs.com/downloads/sc-4.3-linux.tar.gz" +CONNECT_URL="https://saucelabs.com/downloads/sc-4.3.6-linux.tar.gz" CONNECT_DIR="/tmp/sauce-connect-$RANDOM" -CONNECT_DOWNLOAD="sc-4.3-linux.tar.gz" +CONNECT_DOWNLOAD="sc-4.3.6-linux.tar.gz" CONNECT_LOG="$LOGS_DIR/sauce-connect" CONNECT_STDOUT="$LOGS_DIR/sauce-connect.stdout" From d213a499f3a047fa1e0c0a70a570ab5d41e5c0a1 Mon Sep 17 00:00:00 2001 From: Julie Ralph Date: Wed, 11 Feb 2015 17:08:39 -0800 Subject: [PATCH 005/489] chore(ci): make all browserstack tests allowed failures --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 49139f994228..d07f25bb7938 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,9 @@ env: matrix: allow_failures: - env: "JOB=unit BROWSER_PROVIDER=browserstack" + - env: "JOB=docs-e2e BROWSER_PROVIDER=browserstack" + - env: "JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=browserstack" + - env: "JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=browserstack" install: # - npm config set registry http://23.251.144.68 From 93ab22b95590a6a2ec5918dfea391667002f5061 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 13 Feb 2015 11:09:32 +0000 Subject: [PATCH 006/489] perf(ngOptions): only watch labels if a display expression is specified #11052 --- src/ng/directive/ngOptions.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ng/directive/ngOptions.js b/src/ng/directive/ngOptions.js index f6ec5f227c0b..55b8d42faa5d 100644 --- a/src/ng/directive/ngOptions.js +++ b/src/ng/directive/ngOptions.js @@ -267,10 +267,14 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { Object.keys(values).forEach(function getWatchable(key) { var locals = getLocals(values[key], key); - var label = displayFn(scope, locals); var selectValue = getTrackByValue(values[key], locals); watchedArray.push(selectValue); - watchedArray.push(label); + + // Only need to watch the displayFn if there is a specific label expression + if (match[2]) { + var label = displayFn(scope, locals); + watchedArray.push(label); + } }); return watchedArray; }), From 7c066e2c79dde0457a6a4011b2556254679151f2 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 13 Feb 2015 11:49:18 +0000 Subject: [PATCH 007/489] test(ngSanitize): add tests for `decodeEntities` --- test/ngSanitize/sanitizeSpec.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/ngSanitize/sanitizeSpec.js b/test/ngSanitize/sanitizeSpec.js index 2642bdf6fde9..a7d356d5472c 100644 --- a/test/ngSanitize/sanitizeSpec.js +++ b/test/ngSanitize/sanitizeSpec.js @@ -515,6 +515,16 @@ describe('decodeEntities', function() { window.hiddenPre = origHiddenPre; }); + it('should unescape text', function() { + htmlParser('a<div>&</div>c', handler); + expect(text).toEqual('a
&
c'); + }); + + it('should preserve whitespace', function() { + htmlParser(' a&b ', handler); + expect(text).toEqual(' a&b '); + }); + it('should use innerText if textContent is not available (IE<9)', function() { window.hiddenPre = { innerText: 'INNER_TEXT' From 3ecffe3bd0fef1d3d2a64923bd8973598af1dff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rouven=20We=C3=9Fling?= Date: Fri, 13 Feb 2015 11:49:18 +0000 Subject: [PATCH 008/489] refactor(ngSanitize): remove workarounds for IE8 Closes #10758 --- src/ngSanitize/sanitize.js | 21 ++++--------------- test/ngSanitize/sanitizeSpec.js | 37 +-------------------------------- 2 files changed, 5 insertions(+), 53 deletions(-) diff --git a/src/ngSanitize/sanitize.js b/src/ngSanitize/sanitize.js index 50210fea05c1..a23fc1b12e3f 100644 --- a/src/ngSanitize/sanitize.js +++ b/src/ngSanitize/sanitize.js @@ -413,7 +413,6 @@ function htmlParser(html, handler) { } var hiddenPre=document.createElement("pre"); -var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; /** * decodes all entities into regular string * @param value @@ -422,22 +421,10 @@ var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; function decodeEntities(value) { if (!value) { return ''; } - // Note: IE8 does not preserve spaces at the start/end of innerHTML - // so we must capture them and reattach them afterward - var parts = spaceRe.exec(value); - var spaceBefore = parts[1]; - var spaceAfter = parts[3]; - var content = parts[2]; - if (content) { - hiddenPre.innerHTML=content.replace(/&
c'); @@ -524,34 +519,4 @@ describe('decodeEntities', function() { htmlParser(' a&b ', handler); expect(text).toEqual(' a&b '); }); - - it('should use innerText if textContent is not available (IE<9)', function() { - window.hiddenPre = { - innerText: 'INNER_TEXT' - }; - inject(function($sanitize) { - htmlParser('text', handler); - expect(text).toEqual('INNER_TEXT'); - }); - }); - it('should use textContent if available', function() { - window.hiddenPre = { - textContent: 'TEXT_CONTENT', - innerText: 'INNER_TEXT' - }; - inject(function($sanitize) { - htmlParser('text', handler); - expect(text).toEqual('TEXT_CONTENT'); - }); - }); - it('should use textContent even if empty', function() { - window.hiddenPre = { - textContent: '', - innerText: 'INNER_TEXT' - }; - inject(function($sanitize) { - htmlParser('text', handler); - expect(text).toEqual(''); - }); - }); }); From 692851a2c1723bc067fe5225cb641a580bb2909d Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Thu, 12 Feb 2015 08:28:13 +0000 Subject: [PATCH 009/489] fix(ngModel): fix issues when parserName is same as validator key For $validate(), it is necessary to store the parseError state in the controller. Otherwise, if the parser name equals a validator key, $validate() will assume a parse error occured if the validator is invalid. Also, setting the validity for the parser now happens after setting validity for the validator key. Otherwise, the parse key is set, and then immediately afterwards the validator key is unset (because parse errors remove all other validations). Fixes #10698 Closes #10850 Closes #11046 --- src/ng/directive/ngModel.js | 29 +++++----- test/ng/directive/ngModelSpec.js | 90 ++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 15 deletions(-) diff --git a/src/ng/directive/ngModel.js b/src/ng/directive/ngModel.js index 1db2283586c4..8d9c6dc19ba5 100644 --- a/src/ng/directive/ngModel.js +++ b/src/ng/directive/ngModel.js @@ -244,6 +244,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ ngModelGet = parsedNgModel, ngModelSet = parsedNgModelAssign, pendingDebounce = null, + parserValid, ctrl = this; this.$$setOptions = function(options) { @@ -516,16 +517,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ // the model although neither viewValue nor the model on the scope changed var modelValue = ctrl.$$rawModelValue; - // Check if the there's a parse error, so we don't unset it accidentially - var parserName = ctrl.$$parserName || 'parse'; - var parserValid = ctrl.$error[parserName] ? false : undefined; - var prevValid = ctrl.$valid; var prevModelValue = ctrl.$modelValue; var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid; - ctrl.$$runValidators(parserValid, modelValue, viewValue, function(allValid) { + ctrl.$$runValidators(modelValue, viewValue, function(allValid) { // If there was no change in validity, don't update the model // This prevents changing an invalid modelValue to undefined if (!allowInvalid && prevValid !== allValid) { @@ -543,12 +540,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ }; - this.$$runValidators = function(parseValid, modelValue, viewValue, doneCallback) { + this.$$runValidators = function(modelValue, viewValue, doneCallback) { currentValidationRunId++; var localValidationRunId = currentValidationRunId; // check parser error - if (!processParseErrors(parseValid)) { + if (!processParseErrors()) { validationDone(false); return; } @@ -558,21 +555,22 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ } processAsyncValidators(); - function processParseErrors(parseValid) { + function processParseErrors() { var errorKey = ctrl.$$parserName || 'parse'; - if (parseValid === undefined) { + if (parserValid === undefined) { setValidity(errorKey, null); } else { - setValidity(errorKey, parseValid); - if (!parseValid) { + if (!parserValid) { forEach(ctrl.$validators, function(v, name) { setValidity(name, null); }); forEach(ctrl.$asyncValidators, function(v, name) { setValidity(name, null); }); - return false; } + // Set the parse error last, to prevent unsetting it, should a $validators key == parserName + setValidity(errorKey, parserValid); + return parserValid; } return true; } @@ -667,7 +665,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ this.$$parseAndValidate = function() { var viewValue = ctrl.$$lastCommittedViewValue; var modelValue = viewValue; - var parserValid = isUndefined(modelValue) ? undefined : true; + parserValid = isUndefined(modelValue) ? undefined : true; if (parserValid) { for (var i = 0; i < ctrl.$parsers.length; i++) { @@ -693,7 +691,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date. // This can happen if e.g. $setViewValue is called from inside a parser - ctrl.$$runValidators(parserValid, modelValue, ctrl.$$lastCommittedViewValue, function(allValid) { + ctrl.$$runValidators(modelValue, ctrl.$$lastCommittedViewValue, function(allValid) { if (!allowInvalid) { // Note: Don't check ctrl.$valid here, as we could have // external validators (e.g. calculated on the server), @@ -814,6 +812,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ // TODO(perf): why not move this to the action fn? if (modelValue !== ctrl.$modelValue) { ctrl.$modelValue = ctrl.$$rawModelValue = modelValue; + parserValid = undefined; var formatters = ctrl.$formatters, idx = formatters.length; @@ -826,7 +825,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue; ctrl.$render(); - ctrl.$$runValidators(undefined, modelValue, viewValue, noop); + ctrl.$$runValidators(modelValue, viewValue, noop); } } diff --git a/test/ng/directive/ngModelSpec.js b/test/ng/directive/ngModelSpec.js index 583414deaa9c..019f078e6fad 100644 --- a/test/ng/directive/ngModelSpec.js +++ b/test/ng/directive/ngModelSpec.js @@ -1221,6 +1221,96 @@ describe('ngModel', function() { expect(ctrl.$validators.mock).toHaveBeenCalledWith('a', 'ab'); expect(ctrl.$validators.mock.calls.length).toEqual(2); }); + + it('should validate correctly when $parser name equals $validator key', function() { + + ctrl.$validators.parserOrValidator = function(value) { + switch (value) { + case 'allInvalid': + case 'parseValid-validatorsInvalid': + case 'stillParseValid-validatorsInvalid': + return false; + default: + return true; + } + }; + + ctrl.$validators.validator = function(value) { + switch (value) { + case 'allInvalid': + case 'parseValid-validatorsInvalid': + case 'stillParseValid-validatorsInvalid': + return false; + default: + return true; + } + }; + + ctrl.$$parserName = 'parserOrValidator'; + ctrl.$parsers.push(function(value) { + switch (value) { + case 'allInvalid': + case 'stillAllInvalid': + case 'parseInvalid-validatorsValid': + case 'stillParseInvalid-validatorsValid': + return undefined; + default: + return value; + } + }); + + //Parser and validators are invalid + scope.$apply('value = "allInvalid"'); + expect(scope.value).toBe('allInvalid'); + expect(ctrl.$error).toEqual({parserOrValidator: true, validator: true}); + + ctrl.$validate(); + expect(scope.value).toEqual('allInvalid'); + expect(ctrl.$error).toEqual({parserOrValidator: true, validator: true}); + + ctrl.$setViewValue('stillAllInvalid'); + expect(scope.value).toBeUndefined(); + expect(ctrl.$error).toEqual({parserOrValidator: true}); + + ctrl.$validate(); + expect(scope.value).toBeUndefined(); + expect(ctrl.$error).toEqual({parserOrValidator: true}); + + //Parser is valid, validators are invalid + scope.$apply('value = "parseValid-validatorsInvalid"'); + expect(scope.value).toBe('parseValid-validatorsInvalid'); + expect(ctrl.$error).toEqual({parserOrValidator: true, validator: true}); + + ctrl.$validate(); + expect(scope.value).toBe('parseValid-validatorsInvalid'); + expect(ctrl.$error).toEqual({parserOrValidator: true, validator: true}); + + ctrl.$setViewValue('stillParseValid-validatorsInvalid'); + expect(scope.value).toBeUndefined(); + expect(ctrl.$error).toEqual({parserOrValidator: true, validator: true}); + + ctrl.$validate(); + expect(scope.value).toBeUndefined(); + expect(ctrl.$error).toEqual({parserOrValidator: true, validator: true}); + + //Parser is invalid, validators are valid + scope.$apply('value = "parseInvalid-validatorsValid"'); + expect(scope.value).toBe('parseInvalid-validatorsValid'); + expect(ctrl.$error).toEqual({}); + + ctrl.$validate(); + expect(scope.value).toBe('parseInvalid-validatorsValid'); + expect(ctrl.$error).toEqual({}); + + ctrl.$setViewValue('stillParseInvalid-validatorsValid'); + expect(scope.value).toBeUndefined(); + expect(ctrl.$error).toEqual({parserOrValidator: true}); + + ctrl.$validate(); + expect(scope.value).toBeUndefined(); + expect(ctrl.$error).toEqual({parserOrValidator: true}); + }); + }); }); From 4fadbe27694a2d4ff683ddb3790755484dec5712 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Fri, 13 Feb 2015 23:49:33 +0100 Subject: [PATCH 010/489] docs($resource): fix list level Closes #11055 --- src/ngResource/resource.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ngResource/resource.js b/src/ngResource/resource.js index 84340b816b4f..3cf9d3a2841e 100644 --- a/src/ngResource/resource.js +++ b/src/ngResource/resource.js @@ -208,6 +208,7 @@ function shallowClearAndCopy(src, dst) { * - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])` * - non-GET instance actions: `instance.$action([parameters], [success], [error])` * + * * Success callback is called with (value, responseHeaders) arguments. Error callback is called * with (httpResponse) argument. * From b676da6a783a84033b6d745aa836052ed64a8441 Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Fri, 13 Feb 2015 22:49:45 -0800 Subject: [PATCH 011/489] perf($compile): avoid .data when fetching required controllers Closes: ##11059 --- src/ng/compile.js | 55 +++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index 34e38137606f..58cda4452eab 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -1840,49 +1840,42 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { function getControllers(directiveName, require, $element, elementControllers) { - var value, retrievalMethod = 'data', optional = false; - var $searchElement = $element; - var match; - if (isString(require)) { - match = require.match(REQUIRE_PREFIX_REGEXP); - require = require.substring(match[0].length); + var value; - if (match[3]) { - if (match[1]) match[3] = null; - else match[1] = match[3]; - } - if (match[1] === '^') { - retrievalMethod = 'inheritedData'; - } else if (match[1] === '^^') { - retrievalMethod = 'inheritedData'; - $searchElement = $element.parent(); - } - if (match[2] === '?') { - optional = true; + if (isString(require)) { + var match = require.match(REQUIRE_PREFIX_REGEXP); + var name = require.substring(match[0].length); + var inheritType = match[1] || match[3]; + var optional = match[2] === '?'; + + //If only parents then start at the parent element + if (inheritType === '^^') { + $element = $element.parent(); + //Otherwise attempt getting the controller from elementControllers in case + //the element is transcluded (and has no data) and to avoid .data if possible + } else { + value = elementControllers && elementControllers[name]; + value = value && value.instance; } - value = null; - - if (elementControllers && retrievalMethod === 'data') { - if (value = elementControllers[require]) { - value = value.instance; - } + if (!value) { + var dataName = '$' + name + 'Controller'; + value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName); } - value = value || $searchElement[retrievalMethod]('$' + require + 'Controller'); if (!value && !optional) { throw $compileMinErr('ctreq', "Controller '{0}', required by directive '{1}', can't be found!", - require, directiveName); + name, directiveName); } - return value || null; } else if (isArray(require)) { value = []; - forEach(require, function(require) { - value.push(getControllers(directiveName, require, $element, elementControllers)); - }); + for (var i = 0, ii = require.length; i < ii; i++) { + value[i] = getControllers(directiveName, require[i], $element, elementControllers); + } } - return value; + + return value || null; } From 51683656bf5288a8fd695bd82e6ac4914b763387 Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Thu, 23 Oct 2014 00:27:20 -0700 Subject: [PATCH 012/489] refactor($compile): combining elementControllers and controllers --- src/ng/compile.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index 58cda4452eab..69d9d778b330 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -1614,7 +1614,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var terminalPriority = -Number.MAX_VALUE, newScopeDirective, controllerDirectives = previousCompileContext.controllerDirectives, - controllers, newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective, templateDirective = previousCompileContext.templateDirective, nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective, @@ -1904,8 +1903,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } if (controllerDirectives) { - // TODO: merge `controllers` and `elementControllers` into single object. - controllers = {}; elementControllers = {}; forEach(controllerDirectives, function(directive) { var locals = { @@ -1931,8 +1928,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (!hasElementTranscludeDirective) { $element.data('$' + directive.name + 'Controller', controllerInstance.instance); } - - controllers[directive.name] = controllerInstance; }); } @@ -1947,14 +1942,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { isolateScope.$$isolateBindings, newIsolateScopeDirective, isolateScope); } - if (controllers) { + if (elementControllers) { // Initialize bindToController bindings for new/isolate scopes var scopeDirective = newIsolateScopeDirective || newScopeDirective; var bindings; var controllerForBindings; - if (scopeDirective && controllers[scopeDirective.name]) { + if (scopeDirective && elementControllers[scopeDirective.name]) { bindings = scopeDirective.$$bindings.bindToController; - controller = controllers[scopeDirective.name]; + controller = elementControllers[scopeDirective.name]; if (controller && controller.identifier && bindings) { controllerForBindings = controller; @@ -1963,7 +1958,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { bindings, scopeDirective); } } - forEach(controllers, function(controller) { + forEach(elementControllers, function(controller) { var result = controller(); if (result !== controller.instance && controller === controllerForBindings) { @@ -1974,7 +1969,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { bindings, scopeDirective); } }); - controllers = null; } // PRELINKING From 7148b2dc93360866bd6e479f503ab373d57b9558 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Thu, 12 Feb 2015 21:43:10 -0600 Subject: [PATCH 013/489] fix(templateRequest): avoid throwing syntax error in Android 2.3 Android 2.3 throws an `Uncaught SyntaxError: Unexpected token finally` pointing at this line. Change `.finally` to bracket notation. Fixes #11089 Closes #11051 Closes #11088 --- src/ng/templateRequest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ng/templateRequest.js b/src/ng/templateRequest.js index 94ea64e0ca14..5760dde0b973 100644 --- a/src/ng/templateRequest.js +++ b/src/ng/templateRequest.js @@ -40,7 +40,7 @@ function $TemplateRequestProvider() { }; return $http.get(tpl, httpOptions) - .finally(function() { + ['finally'](function() { handleRequestFn.totalPendingRequests--; }) .then(function(response) { From 5bf710b26a5e3965d27e1cf6b6d289b8231c2e46 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 17 Feb 2015 11:42:43 +0100 Subject: [PATCH 014/489] docs(ngRepeat): clarify 'as' microsyntax usage Closes #11087 --- src/ng/directive/ngRepeat.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ng/directive/ngRepeat.js b/src/ng/directive/ngRepeat.js index 5214acf86345..64a3af5c298d 100644 --- a/src/ng/directive/ngRepeat.js +++ b/src/ng/directive/ngRepeat.js @@ -144,6 +144,11 @@ * For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after * the items have been processed through the filter. * + * Please note that `as [variable name] is not an operator but rather a part of ngRepeat micro-syntax so it can be used only at the end + * (and not as operator, inside an expression). + * + * For example: `item in items | filter : x | orderBy : order | limitTo : limit as results` . + * * @example * This example initializes the scope to a list of names and * then uses `ngRepeat` to display every person: From 2ddb06c0562359ad2253324ed4b04f279b4c889e Mon Sep 17 00:00:00 2001 From: Tamer Aydin Date: Sun, 9 Mar 2014 23:02:59 +0100 Subject: [PATCH 015/489] feat(limitTo): extend the filter to take a beginning index argument Extend the limitTo filter to take an optional argument for beginning index. It provides a slice-alike functionality to manipulate the input. Closes #5355 Closes #10899 --- src/ng/filter/limitTo.js | 17 +++++++-- test/ng/filter/limitToSpec.js | 66 +++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/src/ng/filter/limitTo.js b/src/ng/filter/limitTo.js index df7b6fa3433d..67ffc92c019b 100644 --- a/src/ng/filter/limitTo.js +++ b/src/ng/filter/limitTo.js @@ -17,6 +17,8 @@ * If the number is negative, `limit` number of items from the end of the source array/string * are copied. The `limit` will be trimmed if it exceeds `array.length`. If `limit` is undefined, * the input will be returned unchanged. + * @param {string|number} begin Index at which to begin limitation. As a negative index, `begin` + * indicates an offset from the end of `input`. Defaults to `0`. * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array * had less than `limit` elements. * @@ -88,7 +90,7 @@ */ function limitToFilter() { - return function(input, limit) { + return function(input, limit, begin) { if (Math.abs(Number(limit)) === Infinity) { limit = Number(limit); } else { @@ -99,6 +101,17 @@ function limitToFilter() { if (isNumber(input)) input = input.toString(); if (!isArray(input) && !isString(input)) return input; - return limit >= 0 ? input.slice(0, limit) : input.slice(limit); + begin = (!begin || isNaN(begin)) ? 0 : toInt(begin); + begin = (begin < 0 && begin >= -input.length) ? input.length + begin : begin; + + if (limit >= 0) { + return input.slice(begin, begin + limit); + } else { + if (begin === 0) { + return input.slice(limit, input.length); + } else { + return input.slice(Math.max(0, begin + limit), begin); + } + } }; } diff --git a/test/ng/filter/limitToSpec.js b/test/ng/filter/limitToSpec.js index a15fbbc58556..343290a55c5d 100644 --- a/test/ng/filter/limitToSpec.js +++ b/test/ng/filter/limitToSpec.js @@ -23,6 +23,19 @@ describe('Filter: limitTo', function() { expect(limitTo(number, '3')).toEqual("100"); }); + it('should return the first X items beginning from index Y when X and Y are positive', function() { + expect(limitTo(items, 3, '3')).toEqual(['d', 'e', 'f']); + expect(limitTo(items, '3', 3)).toEqual(['d', 'e', 'f']); + expect(limitTo(str, 3, 3)).toEqual("wxy"); + expect(limitTo(str, '3', '3')).toEqual("wxy"); + }); + + it('should return the first X items beginning from index Y when X is positive and Y is negative', function() { + expect(limitTo(items, 3, '-3')).toEqual(['f', 'g', 'h']); + expect(limitTo(items, '3', -3)).toEqual(['f', 'g', 'h']); + expect(limitTo(str, 3, -3)).toEqual("xyz"); + expect(limitTo(str, '3', '-3')).toEqual("xyz"); + }); it('should return the last X items when X is negative', function() { expect(limitTo(items, -3)).toEqual(['f', 'g', 'h']); @@ -33,6 +46,19 @@ describe('Filter: limitTo', function() { expect(limitTo(number, '-3')).toEqual("045"); }); + it('should return the last X items until index Y when X and Y are negative', function() { + expect(limitTo(items, -3, '-3')).toEqual(['c', 'd', 'e']); + expect(limitTo(items, '-3', -3)).toEqual(['c', 'd', 'e']); + expect(limitTo(str, -3, -3)).toEqual("uvw"); + expect(limitTo(str, '-3', '-3')).toEqual("uvw"); + }); + + it('should return the last X items until index Y when X is negative and Y is positive', function() { + expect(limitTo(items, -3, '4')).toEqual(['b', 'c', 'd']); + expect(limitTo(items, '-3', 4)).toEqual(['b', 'c', 'd']); + expect(limitTo(str, -3, 4)).toEqual("uvw"); + expect(limitTo(str, '-3', '4')).toEqual("uvw"); + }); it('should return an empty array when X = 0', function() { expect(limitTo(items, 0)).toEqual([]); @@ -60,6 +86,18 @@ describe('Filter: limitTo', function() { expect(limitTo(str, undefined)).toEqual(str); }); + it('should take 0 as beginning index value when Y cannot be parsed', function() { + expect(limitTo(items, 3, 'bogus')).toEqual(limitTo(items, 3, 0)); + expect(limitTo(items, -3, 'null')).toEqual(limitTo(items, -3)); + expect(limitTo(items, '3', 'undefined')).toEqual(limitTo(items, '3', 0)); + expect(limitTo(items, '-3', null)).toEqual(limitTo(items, '-3')); + expect(limitTo(items, 3, undefined)).toEqual(limitTo(items, 3, 0)); + expect(limitTo(str, 3, 'bogus')).toEqual(limitTo(str, 3)); + expect(limitTo(str, -3, 'null')).toEqual(limitTo(str, -3, 0)); + expect(limitTo(str, '3', 'undefined')).toEqual(limitTo(str, '3')); + expect(limitTo(str, '-3', null)).toEqual(limitTo(str, '-3', 0)); + expect(limitTo(str, 3, undefined)).toEqual(limitTo(str, 3)); + }); it('should return input if not String or Array or Number', function() { expect(limitTo(null, 1)).toEqual(null); @@ -99,4 +137,32 @@ describe('Filter: limitTo', function() { expect(limitTo(str, -Infinity)).toEqual(str); expect(limitTo(str, '-Infinity')).toEqual(str); }); + + it('should return an empty array if Y exceeds input length', function() { + expect(limitTo(items, '3', 12)).toEqual([]); + expect(limitTo(items, 4, '-12')).toEqual([]); + expect(limitTo(items, -3, '12')).toEqual([]); + expect(limitTo(items, '-4', -12)).toEqual([]); + }); + + it('should return an empty string if Y exceeds input length', function() { + expect(limitTo(str, '3', 12)).toEqual(""); + expect(limitTo(str, 4, '-12')).toEqual(""); + expect(limitTo(str, -3, '12')).toEqual(""); + expect(limitTo(str, '-4', -12)).toEqual(""); + }); + + it('should return the entire string beginning from Y if X is positive and X+Y exceeds input length', function() { + expect(limitTo(items, 7, 3)).toEqual(['d', 'e', 'f', 'g', 'h']); + expect(limitTo(items, 7, -3)).toEqual(['f', 'g', 'h']); + expect(limitTo(str, 6, 3)).toEqual("wxyz"); + expect(limitTo(str, 6, -3)).toEqual("xyz"); + }); + + it('should return the entire string until index Y if X is negative and X+Y exceeds input length', function() { + expect(limitTo(items, -7, 3)).toEqual(['a', 'b', 'c']); + expect(limitTo(items, -7, -3)).toEqual(['a', 'b', 'c', 'd', 'e']); + expect(limitTo(str, -6, 3)).toEqual("tuv"); + expect(limitTo(str, -6, -3)).toEqual("tuvw"); + }); }); From dcb8bb64349a14ee34d54f34a9d5e6bc20dae47d Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Mon, 16 Feb 2015 23:05:43 -0800 Subject: [PATCH 016/489] perf($compile): replace forEach(controller) with plain loops Closes #11084 --- src/ng/compile.js | 70 +++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index 69d9d778b330..f97c780d7061 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -1671,7 +1671,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (!directive.templateUrl && directive.controller) { directiveValue = directive.controller; - controllerDirectives = controllerDirectives || {}; + controllerDirectives = controllerDirectives || createMap(); assertNoDuplicate("'" + directiveName + "' controller", controllerDirectives[directiveName], directive, $compileNode); controllerDirectives[directiveName] = directive; @@ -1877,6 +1877,36 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { return value || null; } + function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope) { + var elementControllers = createMap(); + for (var controllerKey in controllerDirectives) { + var directive = controllerDirectives[controllerKey]; + var locals = { + $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, + $element: $element, + $attrs: attrs, + $transclude: transcludeFn + }; + + var controller = directive.controller; + if (controller == '@') { + controller = attrs[directive.name]; + } + + var controllerInstance = $controller(controller, locals, true, directive.controllerAs); + + // For directives with element transclusion the element is a comment, + // but jQuery .data doesn't support attaching data to comment nodes as it's hard to + // clean up (http://bugs.jquery.com/ticket/8335). + // Instead, we save the controllers for the element in a local hash and attach to .data + // later, once we have the actual element. + elementControllers[directive.name] = controllerInstance; + if (!hasElementTranscludeDirective) { + $element.data('$' + directive.name + 'Controller', controllerInstance.instance); + } + } + return elementControllers; + } function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn, thisLinkFn) { @@ -1903,32 +1933,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } if (controllerDirectives) { - elementControllers = {}; - forEach(controllerDirectives, function(directive) { - var locals = { - $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, - $element: $element, - $attrs: attrs, - $transclude: transcludeFn - }, controllerInstance; - - controller = directive.controller; - if (controller == '@') { - controller = attrs[directive.name]; - } - - controllerInstance = $controller(controller, locals, true, directive.controllerAs); - - // For directives with element transclusion the element is a comment, - // but jQuery .data doesn't support attaching data to comment nodes as it's hard to - // clean up (http://bugs.jquery.com/ticket/8335). - // Instead, we save the controllers for the element in a local hash and attach to .data - // later, once we have the actual element. - elementControllers[directive.name] = controllerInstance; - if (!hasElementTranscludeDirective) { - $element.data('$' + directive.name + 'Controller', controllerInstance.instance); - } - }); + elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope); } if (newIsolateScopeDirective) { @@ -1958,17 +1963,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { bindings, scopeDirective); } } - forEach(elementControllers, function(controller) { - var result = controller(); - if (result !== controller.instance && + for (i in elementControllers) { + controller = elementControllers[i]; + var controllerResult = controller(); + if (controllerResult !== controller.instance && controller === controllerForBindings) { // Remove and re-install bindToController bindings thisLinkFn.$$destroyBindings(); thisLinkFn.$$destroyBindings = - initializeDirectiveBindings(scope, attrs, result, + initializeDirectiveBindings(scope, attrs, controllerResult, bindings, scopeDirective); } - }); + } } // PRELINKING From 8bc638f34f96a36482e89576acc17f9eb846c02d Mon Sep 17 00:00:00 2001 From: Stephen Barker Date: Mon, 9 Feb 2015 15:29:42 -0500 Subject: [PATCH 017/489] feat(ngOptions): add support for disabling an option This patch adds support for disabling options based on model values. The "disable when" syntax allows for listening to changes on those model values, in order to dynamically enable and disable the options. The changes prevent disabled options from being written to the selectCtrl from the model. If a disabled selection is present on the model, normal unknown or empty functionality kicks in. Closes #638 Closes #11017 --- src/ng/directive/ngOptions.js | 77 ++++++--- test/ng/directive/ngOptionsSpec.js | 249 +++++++++++++++++++++++++++++ 2 files changed, 302 insertions(+), 24 deletions(-) diff --git a/src/ng/directive/ngOptions.js b/src/ng/directive/ngOptions.js index 55b8d42faa5d..199ea81a791d 100644 --- a/src/ng/directive/ngOptions.js +++ b/src/ng/directive/ngOptions.js @@ -94,15 +94,20 @@ var ngOptionsMinErr = minErr('ngOptions'); * * `label` **`for`** `value` **`in`** `array` * * `select` **`as`** `label` **`for`** `value` **`in`** `array` * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` + * * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array` * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr` + * * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array` **`track by`** `trackexpr` * * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr` * (for including a filter with `track by`) * * for object data sources: * * `label` **`for (`**`key` **`,`** `value`**`) in`** `object` * * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object` * * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object` + * * `label` **`disable when`** `disable` **`for (`**`key`**`,`** `value`**`) in`** `object` * * `select` **`as`** `label` **`group by`** `group` * **`for` `(`**`key`**`,`** `value`**`) in`** `object` + * * `select` **`as`** `label` **`disable when`** `disable` + * **`for` `(`**`key`**`,`** `value`**`) in`** `object` * * Where: * @@ -116,6 +121,8 @@ var ngOptionsMinErr = minErr('ngOptions'); * element. If not specified, `select` expression will default to `value`. * * `group`: The result of this expression will be used to group options using the `` * DOM element. + * * `disable`: The result of this expression will be used to disable the rendered `
'); + compileElement('
'); expect(element.attr('role')).toBe(undefined); }); + it('should add missing role="slider" to custom input', function() { - scope.$apply('val = true'); - compileInput('
'); + compileElement('
'); expect(element.attr('role')).toBe('slider'); }); + it('should not add a role to a native range input', function() { - scope.$apply('val = true'); - compileInput('
'); + compileElement('
'); expect(element.attr('role')).toBe(undefined); }); }); @@ -234,16 +233,16 @@ describe('$aria', function() { beforeEach(injectScopeAndCompiler); it('should not attach aria-checked', function() { - compileInput("
"); + compileElement("
"); expect(element.attr('aria-checked')).toBeUndefined(); - compileInput("
"); + compileElement("
"); expect(element.attr('aria-checked')).toBeUndefined(); - compileInput("
"); + compileElement("
"); expect(element.attr('aria-checked')).toBeUndefined(); - compileInput("
"); + compileElement("
"); expect(element.attr('aria-checked')).toBeUndefined(); }); }); @@ -253,7 +252,7 @@ describe('$aria', function() { it('should attach itself to input elements', function() { scope.$apply('val = false'); - compileInput(""); + compileElement(""); expect(element.attr('aria-disabled')).toBe('false'); scope.$apply('val = true'); @@ -262,7 +261,7 @@ describe('$aria', function() { it('should attach itself to textarea elements', function() { scope.$apply('val = false'); - compileInput(''); + compileElement(''); expect(element.attr('aria-disabled')).toBe('false'); scope.$apply('val = true'); @@ -271,7 +270,7 @@ describe('$aria', function() { it('should attach itself to button elements', function() { scope.$apply('val = false'); - compileInput(''); + compileElement(''); expect(element.attr('aria-disabled')).toBe('false'); scope.$apply('val = true'); @@ -280,7 +279,7 @@ describe('$aria', function() { it('should attach itself to select elements', function() { scope.$apply('val = false'); - compileInput(''); + compileElement(''); expect(element.attr('aria-disabled')).toBe('false'); scope.$apply('val = true'); @@ -323,7 +322,7 @@ describe('$aria', function() { beforeEach(injectScopeAndCompiler); it('should attach aria-invalid to input', function() { - compileInput(''); + compileElement(''); scope.$apply("txtInput='LTten'"); expect(element.attr('aria-invalid')).toBe('true'); @@ -332,7 +331,7 @@ describe('$aria', function() { }); it('should not attach itself if aria-invalid is already present', function() { - compileInput(''); + compileElement(''); scope.$apply("txtInput='LTten'"); expect(element.attr('aria-invalid')).toBe('userSetValue'); }); @@ -346,7 +345,7 @@ describe('$aria', function() { it('should not attach aria-invalid if the option is disabled', function() { scope.$apply("txtInput='LTten'"); - compileInput(''); + compileElement(''); expect(element.attr('aria-invalid')).toBeUndefined(); }); }); @@ -355,7 +354,7 @@ describe('$aria', function() { beforeEach(injectScopeAndCompiler); it('should attach aria-required to input', function() { - compileInput(''); + compileElement(''); expect(element.attr('aria-required')).toBe('true'); scope.$apply("val='input is valid now'"); @@ -363,7 +362,7 @@ describe('$aria', function() { }); it('should attach aria-required to textarea', function() { - compileInput(''); + compileElement(''); expect(element.attr('aria-required')).toBe('true'); scope.$apply("val='input is valid now'"); @@ -371,7 +370,7 @@ describe('$aria', function() { }); it('should attach aria-required to select', function() { - compileInput(''); + compileElement(''); expect(element.attr('aria-required')).toBe('true'); scope.$apply("val='input is valid now'"); @@ -379,7 +378,7 @@ describe('$aria', function() { }); it('should attach aria-required to ngRequired', function() { - compileInput(''); + compileElement(''); expect(element.attr('aria-required')).toBe('true'); scope.$apply("val='input is valid now'"); @@ -387,16 +386,16 @@ describe('$aria', function() { }); it('should not attach itself if aria-required is already present', function() { - compileInput(""); + compileElement(""); expect(element.attr('aria-required')).toBe('userSetValue'); - compileInput(""); + compileElement(""); expect(element.attr('aria-required')).toBe('userSetValue'); - compileInput(""); + compileElement(""); expect(element.attr('aria-required')).toBe('userSetValue'); - compileInput(""); + compileElement(""); expect(element.attr('aria-required')).toBe('userSetValue'); }); }); @@ -408,13 +407,13 @@ describe('$aria', function() { beforeEach(injectScopeAndCompiler); it('should not add the aria-required attribute', function() { - compileInput(""); + compileElement(""); expect(element.attr('aria-required')).toBeUndefined(); - compileInput(""); + compileElement(""); expect(element.attr('aria-required')).toBeUndefined(); - compileInput(""); + compileElement(""); expect(element.attr('aria-required')).toBeUndefined(); }); }); @@ -423,20 +422,20 @@ describe('$aria', function() { beforeEach(injectScopeAndCompiler); it('should attach itself to textarea', function() { - compileInput(''); + compileElement(''); expect(element.attr('aria-multiline')).toBe('true'); }); it('should attach itself role="textbox"', function() { - compileInput('
'); + compileElement('
'); expect(element.attr('aria-multiline')).toBe('true'); }); it('should not attach itself if aria-multiline is already present', function() { - compileInput(''); + compileElement(''); expect(element.attr('aria-multiline')).toBe('userSetValue'); - compileInput('
'); + compileElement('
'); expect(element.attr('aria-multiline')).toBe('userSetValue'); }); }); @@ -448,12 +447,12 @@ describe('$aria', function() { beforeEach(injectScopeAndCompiler); it('should not attach itself to textarea', function() { - compileInput(''); + compileElement(''); expect(element.attr('aria-multiline')).toBeUndefined(); }); it('should not attach itself role="textbox"', function() { - compileInput('
'); + compileElement('
'); expect(element.attr('aria-multiline')).toBeUndefined(); }); }); @@ -511,12 +510,12 @@ describe('$aria', function() { it('should not attach itself', function() { scope.$apply('val = 50'); - compileInput(''); + compileElement(''); expect(element.attr('aria-valuenow')).toBeUndefined(); expect(element.attr('aria-valuemin')).toBeUndefined(); expect(element.attr('aria-valuemax')).toBeUndefined(); - compileInput('
'); + compileElement('
'); expect(element.attr('aria-valuenow')).toBeUndefined(); expect(element.attr('aria-valuemin')).toBeUndefined(); expect(element.attr('aria-valuemax')).toBeUndefined(); @@ -527,32 +526,32 @@ describe('$aria', function() { beforeEach(injectScopeAndCompiler); it('should attach tabindex to role="checkbox", ng-click, and ng-dblclick', function() { - compileInput('
'); + compileElement('
'); expect(element.attr('tabindex')).toBe('0'); - compileInput('
'); + compileElement('
'); expect(element.attr('tabindex')).toBe('0'); - compileInput('
'); + compileElement('
'); expect(element.attr('tabindex')).toBe('0'); }); it('should not attach tabindex if it is already on an element', function() { - compileInput('
'); + compileElement('
'); expect(element.attr('tabindex')).toBe('userSetValue'); - compileInput('
'); + compileElement('
'); expect(element.attr('tabindex')).toBe('userSetValue'); - compileInput('
'); + compileElement('
'); expect(element.attr('tabindex')).toBe('userSetValue'); - compileInput('
'); + compileElement('
'); expect(element.attr('tabindex')).toBe('userSetValue'); }); it('should set proper tabindex values for radiogroup', function() { - compileInput('
' + + compileElement('
' + '
1
' + '
2
' + '
'); @@ -605,7 +604,7 @@ describe('$aria', function() { scope.someAction = function() {}; clickFn = spyOn(scope, 'someAction'); - compileInput('
'); + compileElement('
'); element.triggerHandler({type: 'keypress', keyCode: 32}); @@ -614,7 +613,7 @@ describe('$aria', function() { }); it('should update bindings when keypress handled', function() { - compileInput('
{{text}}
'); + compileElement('
{{text}}
'); expect(element.text()).toBe(''); spyOn(scope.$root, '$digest').andCallThrough(); element.triggerHandler({ type: 'keypress', keyCode: 13 }); @@ -623,22 +622,22 @@ describe('$aria', function() { }); it('should pass $event to ng-click handler as local', function() { - compileInput('
{{event.type}}' + - '{{event.keyCode}}
'); + compileElement('
{{event.type}}' + + '{{event.keyCode}}
'); expect(element.text()).toBe(''); element.triggerHandler({ type: 'keypress', keyCode: 13 }); expect(element.text()).toBe('keypress13'); }); it('should not bind keypress to elements not in the default config', function() { - compileInput(''); + compileElement(''); expect(element.text()).toBe(''); element.triggerHandler({ type: 'keypress', keyCode: 13 }); expect(element.text()).toBe(''); }); }); - describe('actions when bindKeypress set to false', function() { + describe('actions when bindKeypress is set to false', function() { beforeEach(configAriaProvider({ bindKeypress: false })); @@ -663,16 +662,16 @@ describe('$aria', function() { beforeEach(injectScopeAndCompiler); it('should not add a tabindex attribute', function() { - compileInput('
'); + compileElement('
'); expect(element.attr('tabindex')).toBeUndefined(); - compileInput('
'); + compileElement('
'); expect(element.attr('tabindex')).toBeUndefined(); - compileInput('
'); + compileElement('
'); expect(element.attr('tabindex')).toBeUndefined(); - compileInput('
'); + compileElement('
'); expect(element.attr('tabindex')).toBeUndefined(); }); }); From a3a8bc841fedeb4d195995efdff5f4a68f9d3e79 Mon Sep 17 00:00:00 2001 From: Marcy Sutton Date: Mon, 2 Mar 2015 10:39:49 +0000 Subject: [PATCH 062/489] feat(ngAria): add `button` role to `ngClick` Closes #9254 Closes #10318 --- docs/content/guide/accessibility.ngdoc | 10 ++++++---- src/ngAria/aria.js | 11 ++++++++--- test/ngAria/ariaSpec.js | 10 ++++++++++ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/docs/content/guide/accessibility.ngdoc b/docs/content/guide/accessibility.ngdoc index 0865c6e0cfdc..51a3cd34955f 100644 --- a/docs/content/guide/accessibility.ngdoc +++ b/docs/content/guide/accessibility.ngdoc @@ -213,11 +213,13 @@ The default CSS for `ngHide`, the inverse method to `ngShow`, makes ngAria redun If `ng-click` or `ng-dblclick` is encountered, ngAria will add `tabindex="0"` if it isn't there already. -For `ng-click`, keypress will also be bound to `div` and `li` elements. You can turn this -functionality on or off with the `bindKeypress` configuration option. +To fix widespread accessibility problems with `ng-click` on div elements, ngAria will dynamically +bind keypress by default as long as the element isn't an anchor, button, input or textarea. +You can turn this functionality on or off with the `bindKeypress` configuration option. ngAria +will also add the `button` role to communicate to users of assistive technologies. -For `ng-dblclick`, you must manually add `ng-keypress` to non-interactive elements such as `div` -or `taco-button` to enable keyboard access. +For `ng-dblclick`, you must still manually add `ng-keypress` and role to non-interactive elements such +as `div` or `taco-button` to enable keyboard access.

Example

```html diff --git a/src/ngAria/aria.js b/src/ngAria/aria.js index 6cebb0a06949..91a96979d985 100644 --- a/src/ngAria/aria.js +++ b/src/ngAria/aria.js @@ -22,13 +22,13 @@ * * | Directive | Supported Attributes | * |---------------------------------------------|----------------------------------------------------------------------------------------| - * | {@link ng.directive:ngModel ngModel} | aria-checked, aria-valuemin, aria-valuemax, aria-valuenow, aria-invalid, aria-required | * | {@link ng.directive:ngDisabled ngDisabled} | aria-disabled | * | {@link ng.directive:ngShow ngShow} | aria-hidden | * | {@link ng.directive:ngHide ngHide} | aria-hidden | - * | {@link ng.directive:ngClick ngClick} | tabindex, keypress event | * | {@link ng.directive:ngDblclick ngDblclick} | tabindex | * | {@link module:ngMessages ngMessages} | aria-live | + * | {@link ng.directive:ngModel ngModel} | aria-checked, aria-valuemin, aria-valuemax, aria-valuenow, aria-invalid, aria-required, input roles | + * | {@link ng.directive:ngClick ngClick} | tabindex, keypress event, button role | * * Find out more information about each directive by reading the * {@link guide/accessibility ngAria Developer Guide}. @@ -317,17 +317,22 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) { var fn = $parse(attr.ngClick, /* interceptorFn */ null, /* expensiveChecks */ true); return function(scope, elem, attr) { + var nodeBlackList = ['BUTTON', 'A', 'INPUT', 'TEXTAREA']; + function isNodeOneOf(elem, nodeTypeArray) { if (nodeTypeArray.indexOf(elem[0].nodeName) !== -1) { return true; } } + if (!elem.attr('role') && !isNodeOneOf(elem, nodeBlackList)) { + elem.attr('role', 'button'); + } if ($aria.config('tabindex') && !elem.attr('tabindex')) { elem.attr('tabindex', 0); } - if ($aria.config('bindKeypress') && !attr.ngKeypress && isNodeOneOf(elem, ['DIV', 'LI'])) { + if ($aria.config('bindKeypress') && !attr.ngKeypress && !isNodeOneOf(elem, nodeBlackList)) { elem.on('keypress', function(event) { if (event.keyCode === 32 || event.keyCode === 13) { scope.$apply(callback); diff --git a/test/ngAria/ariaSpec.js b/test/ngAria/ariaSpec.js index c0c89f05b25f..8da1f83c7611 100644 --- a/test/ngAria/ariaSpec.js +++ b/test/ngAria/ariaSpec.js @@ -195,6 +195,16 @@ describe('$aria', function() { describe('roles for custom inputs', function() { beforeEach(injectScopeAndCompiler); + it('should add missing role="button" to custom input', function() { + compileElement('
'); + expect(element.attr('role')).toBe('button'); + }); + + it('should not add role="button" to anchor', function() { + compileElement(''); + expect(element.attr('role')).not.toBe('button'); + }); + it('should add missing role="checkbox" to custom input', function() { compileElement('
'); expect(element.attr('role')).toBe('checkbox'); From ec1d39c8f5773ee41df1ada06bc9a37c73827cc8 Mon Sep 17 00:00:00 2001 From: Brian Ford Date: Mon, 8 Dec 2014 15:45:54 -0800 Subject: [PATCH 063/489] docs(TRIAGING.md): improve process around `PRs plz!` label Closes #10375 --- TRIAGING.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/TRIAGING.md b/TRIAGING.md index 8ae46a574334..edb30bb8ef11 100644 --- a/TRIAGING.md +++ b/TRIAGING.md @@ -55,7 +55,11 @@ This process based on the idea of minimizing user pain * inconvenience - causes ugly/boilerplate code in apps 1. Label `component: *` * In rare cases, it's ok to have multiple components. -1. Label `PRs plz!` - These issues are good targets for PRs from the open source community. Apply to issues where the problem and solution are well defined in the comments, and it's not too complex. +1. Label `PRs plz!` - These issues are good targets for PRs from the open source community. In addition to applying this label, you must: + * Leave a comment explaining the problem and solution so someone can easily finish it. + * Assign the issue to yourself. + * Give feedback on PRs addressing this issue. + * You are responsible for mentoring contributors helping with this issue. 1. Label `origin: google` for issues from Google 1. Assign a milestone: * Backlog - triaged fixes and features, should be the default choice From 3bd03ff56f898cddc078791b85a127fafad3ec3c Mon Sep 17 00:00:00 2001 From: Caitlin Potter Date: Mon, 8 Dec 2014 09:15:39 -0500 Subject: [PATCH 064/489] fix($browser): don't crash if history.state access causes error in IE Reportedly, MSIE can throw under certain conditions when fetching this attribute. We don't have a reliable reproduction for this but it doesn't do any real harm to wrap access to this variable in a try-catch block. Fixes #10367 Closes #10369 --- src/ng/browser.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ng/browser.js b/src/ng/browser.js index af2dd70e76a9..8bd6b424bff8 100644 --- a/src/ng/browser.js +++ b/src/ng/browser.js @@ -233,11 +233,19 @@ function Browser(window, document, $log, $sniffer) { fireUrlChange(); } + function getCurrentState() { + try { + return history.state; + } catch (e) { + // MSIE can reportedly throw when there is no state (UNCONFIRMED). + } + } + // This variable should be used *only* inside the cacheState function. var lastCachedState = null; function cacheState() { // This should be the only place in $browser where `history.state` is read. - cachedState = window.history.state; + cachedState = getCurrentState(); cachedState = isUndefined(cachedState) ? null : cachedState; // Prevent callbacks fo fire twice if both hashchange & popstate were fired. From c93f5f6dbf91eff0aa9b09d63740cf88f30a04c6 Mon Sep 17 00:00:00 2001 From: Casey Howard Date: Thu, 11 Dec 2014 10:10:58 -0800 Subject: [PATCH 065/489] fix(filterFilter): Fix filtering using an object expression when the filter value is undefined Fixes #10419 Closes #10424 --- src/ng/filter/filter.js | 2 +- test/ng/filter/filterSpec.js | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ng/filter/filter.js b/src/ng/filter/filter.js index 624253a2e73a..302e4ddabb27 100644 --- a/src/ng/filter/filter.js +++ b/src/ng/filter/filter.js @@ -213,7 +213,7 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatc } else if (expectedType === 'object') { for (key in expected) { var expectedVal = expected[key]; - if (isFunction(expectedVal)) { + if (isFunction(expectedVal) || isUndefined(expectedVal)) { continue; } diff --git a/test/ng/filter/filterSpec.js b/test/ng/filter/filterSpec.js index 97cfae8444ca..ab3b76e7a5c5 100644 --- a/test/ng/filter/filterSpec.js +++ b/test/ng/filter/filterSpec.js @@ -48,6 +48,15 @@ describe('Filter: filter', function() { }); + it('should ignore undefined properties of the expression object', function() { + var items = [{name: 'a'}, {name: 'abc'}]; + expect(filter(items, {name: undefined})).toEqual([{name: 'a'}, {name: 'abc'}]); + + items = [{first: 'misko'}, {deep: {first: 'misko'}}, {deep: {last: 'hevery'}}]; + expect(filter(items, {deep: {first: undefined}})).toEqual([{deep: {first: 'misko'}}, {deep: {last: 'hevery'}}]); + }); + + it('should take function as predicate', function() { var items = [{name: 'a'}, {name: 'abc', done: true}]; expect(filter(items, function(i) {return i.done;}).length).toBe(1); From 16411279d00a650aecafcbad5e5b60b64d7339c1 Mon Sep 17 00:00:00 2001 From: Shahar Talmi Date: Mon, 2 Mar 2015 13:24:30 +0200 Subject: [PATCH 066/489] refactor($browser): split cookie access into $$cookieReader and $$cookieWriter services --- angularFiles.js | 8 +- src/AngularPublic.js | 6 +- src/ng/browser.js | 83 ----------- src/ng/cookieReader.js | 55 ++++++++ src/ng/http.js | 6 +- src/ngCookies/cookieWriter.js | 44 ++++++ src/ngCookies/cookies.js | 10 +- src/ngMock/angular-mocks.js | 21 --- test/ng/browserSpecs.js | 215 ----------------------------- test/ng/cookieReaderSpec.js | 103 ++++++++++++++ test/ng/httpSpec.js | 33 ++--- test/ngCookies/cookieWriterSpec.js | 131 ++++++++++++++++++ test/ngCookies/cookiesSpec.js | 107 +++++++------- 13 files changed, 423 insertions(+), 399 deletions(-) create mode 100644 src/ng/cookieReader.js create mode 100644 src/ngCookies/cookieWriter.js create mode 100644 test/ng/cookieReaderSpec.js create mode 100644 test/ngCookies/cookieWriterSpec.js diff --git a/angularFiles.js b/angularFiles.js index 696bd8e78ec8..20bd1c3edded 100755 --- a/angularFiles.js +++ b/angularFiles.js @@ -40,6 +40,7 @@ var angularFiles = { 'src/ng/timeout.js', 'src/ng/urlUtils.js', 'src/ng/window.js', + 'src/ng/cookieReader.js', 'src/ng/filter.js', 'src/ng/filter/filter.js', @@ -89,7 +90,8 @@ var angularFiles = { 'src/ngAnimate/animate.js' ], 'ngCookies': [ - 'src/ngCookies/cookies.js' + 'src/ngCookies/cookies.js', + 'src/ngCookies/cookieWriter.js' ], 'ngMessages': [ 'src/ngMessages/messages.js' @@ -162,7 +164,7 @@ var angularFiles = { 'src/publishExternalApis.js', '@angularSrcModules', '@angularScenario', - '@angularTest', + '@angularTest' ], 'karmaExclude': [ @@ -197,7 +199,7 @@ var angularFiles = { 'src/publishExternalApis.js', '@angularSrcModules', '@angularScenario', - '@angularTest', + '@angularTest' ], 'karmaJqueryExclude': [ diff --git a/src/AngularPublic.js b/src/AngularPublic.js index b81257b9fff7..31e8483ee6bf 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -84,7 +84,8 @@ $$RAFProvider, $$AsyncCallbackProvider, $WindowProvider, - $$jqLiteProvider + $$jqLiteProvider, + $$CookieReaderProvider */ @@ -238,7 +239,8 @@ function publishExternalAPI(angular) { $window: $WindowProvider, $$rAF: $$RAFProvider, $$asyncCallback: $$AsyncCallbackProvider, - $$jqLite: $$jqLiteProvider + $$jqLite: $$jqLiteProvider, + $$cookieReader: $$CookieReaderProvider }); } ]); diff --git a/src/ng/browser.js b/src/ng/browser.js index 8bd6b424bff8..179f060ed019 100644 --- a/src/ng/browser.js +++ b/src/ng/browser.js @@ -332,89 +332,6 @@ function Browser(window, document, $log, $sniffer) { return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : ''; }; - ////////////////////////////////////////////////////////////// - // Cookies API - ////////////////////////////////////////////////////////////// - var lastCookies = {}; - var lastCookieString = ''; - var cookiePath = self.baseHref(); - - function safeDecodeURIComponent(str) { - try { - return decodeURIComponent(str); - } catch (e) { - return str; - } - } - - /** - * @name $browser#cookies - * - * @param {string=} name Cookie name - * @param {string=} value Cookie value - * - * @description - * The cookies method provides a 'private' low level access to browser cookies. - * It is not meant to be used directly, use the $cookie service instead. - * - * The return values vary depending on the arguments that the method was called with as follows: - * - * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify - * it - * - cookies(name, value) -> set name to value, if value is undefined delete the cookie - * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that - * way) - * - * @returns {Object} Hash of all cookies (if called without any parameter) - */ - self.cookies = function(name, value) { - var cookieLength, cookieArray, cookie, i, index; - - if (name) { - if (value === undefined) { - rawDocument.cookie = encodeURIComponent(name) + "=;path=" + cookiePath + - ";expires=Thu, 01 Jan 1970 00:00:00 GMT"; - } else { - if (isString(value)) { - cookieLength = (rawDocument.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) + - ';path=' + cookiePath).length + 1; - - // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum: - // - 300 cookies - // - 20 cookies per unique domain - // - 4096 bytes per cookie - if (cookieLength > 4096) { - $log.warn("Cookie '" + name + - "' possibly not set or overflowed because it was too large (" + - cookieLength + " > 4096 bytes)!"); - } - } - } - } else { - if (rawDocument.cookie !== lastCookieString) { - lastCookieString = rawDocument.cookie; - cookieArray = lastCookieString.split("; "); - lastCookies = {}; - - for (i = 0; i < cookieArray.length; i++) { - cookie = cookieArray[i]; - index = cookie.indexOf('='); - if (index > 0) { //ignore nameless cookies - name = safeDecodeURIComponent(cookie.substring(0, index)); - // the first value that is seen for a cookie is the most - // specific one. values for the same cookie name that - // follow are for less specific paths. - if (lastCookies[name] === undefined) { - lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1)); - } - } - } - } - return lastCookies; - } - }; - - /** * @name $browser#defer * @param {function()} fn A function, who's execution should be deferred. diff --git a/src/ng/cookieReader.js b/src/ng/cookieReader.js new file mode 100644 index 000000000000..53bc279f4269 --- /dev/null +++ b/src/ng/cookieReader.js @@ -0,0 +1,55 @@ +'use strict'; + +/** + * @name $$cookieReader + * @requires $document + * + * @description + * This is a private service for reading cookies used by $http and ngCookies + * + * @return {Object} a key/value map of the current cookies + */ +function $$CookieReader($document) { + var rawDocument = $document[0]; + var lastCookies = {}; + var lastCookieString = ''; + + function safeDecodeURIComponent(str) { + try { + return decodeURIComponent(str); + } catch (e) { + return str; + } + } + + return function() { + var cookieArray, cookie, i, index, name; + + if (rawDocument.cookie !== lastCookieString) { + lastCookieString = rawDocument.cookie; + cookieArray = lastCookieString.split('; '); + lastCookies = {}; + + for (i = 0; i < cookieArray.length; i++) { + cookie = cookieArray[i]; + index = cookie.indexOf('='); + if (index > 0) { //ignore nameless cookies + name = safeDecodeURIComponent(cookie.substring(0, index)); + // the first value that is seen for a cookie is the most + // specific one. values for the same cookie name that + // follow are for less specific paths. + if (lastCookies[name] === undefined) { + lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1)); + } + } + } + } + return lastCookies; + }; +} + +$$CookieReader.$inject = ['$document']; + +function $$CookieReaderProvider() { + this.$get = $$CookieReader; +} diff --git a/src/ng/http.js b/src/ng/http.js index dc37c1625a09..95a33ae7a1fb 100644 --- a/src/ng/http.js +++ b/src/ng/http.js @@ -220,8 +220,8 @@ function $HttpProvider() { **/ var interceptorFactories = this.interceptors = []; - this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector', - function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) { + this.$get = ['$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector', + function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) { var defaultCache = $cacheFactory('$http'); @@ -1066,7 +1066,7 @@ function $HttpProvider() { // send the request to the backend if (isUndefined(cachedResp)) { var xsrfValue = urlIsSameOrigin(config.url) - ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName] + ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName] : undefined; if (xsrfValue) { reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue; diff --git a/src/ngCookies/cookieWriter.js b/src/ngCookies/cookieWriter.js new file mode 100644 index 000000000000..4cf714fbea50 --- /dev/null +++ b/src/ngCookies/cookieWriter.js @@ -0,0 +1,44 @@ +'use strict'; + +/** + * @name $$cookieWriter + * @requires $document + * + * @description + * This is a private service for writing cookies + * + * @param {string} name Cookie name + * @param {string=} value Cookie value (if undefined, cookie will be deleted) + */ +function $$CookieWriter($document, $log, $browser) { + var cookiePath = $browser.baseHref(); + var rawDocument = $document[0]; + + return function(name, value) { + if (value === undefined) { + rawDocument.cookie = encodeURIComponent(name) + "=;path=" + cookiePath + + ";expires=Thu, 01 Jan 1970 00:00:00 GMT"; + } else { + if (angular.isString(value)) { + var cookieLength = (rawDocument.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) + + ';path=' + cookiePath).length + 1; + + // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum: + // - 300 cookies + // - 20 cookies per unique domain + // - 4096 bytes per cookie + if (cookieLength > 4096) { + $log.warn("Cookie '" + name + + "' possibly not set or overflowed because it was too large (" + + cookieLength + " > 4096 bytes)!"); + } + } + } + }; +} + +$$CookieWriter.$inject = ['$document', '$log', '$browser']; + +angular.module('ngCookies').provider('$$cookieWriter', function $$CookieWriterProvider() { + this.$get = $$CookieWriter; +}); diff --git a/src/ngCookies/cookies.js b/src/ngCookies/cookies.js index fcb66e62d16a..d458243b25d1 100644 --- a/src/ngCookies/cookies.js +++ b/src/ngCookies/cookies.js @@ -43,7 +43,7 @@ angular.module('ngCookies', ['ng']). * }]); * ``` */ - factory('$cookies', ['$rootScope', '$browser', function($rootScope, $browser) { + factory('$cookies', ['$rootScope', '$browser', '$$cookieReader', '$$cookieWriter', function($rootScope, $browser, $$cookieReader, $$cookieWriter) { var cookies = {}, lastCookies = {}, lastBrowserCookies, @@ -53,7 +53,7 @@ angular.module('ngCookies', ['ng']). //creates a poller fn that copies all cookies from the $browser to service & inits the service $browser.addPollFn(function() { - var currentCookies = $browser.cookies(); + var currentCookies = $$cookieReader(); if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl lastBrowserCookies = currentCookies; copy(currentCookies, lastCookies); @@ -85,7 +85,7 @@ angular.module('ngCookies', ['ng']). //delete any cookies deleted in $cookies for (name in lastCookies) { if (isUndefined(cookies[name])) { - $browser.cookies(name, undefined); + $$cookieWriter(name, undefined); } } @@ -97,7 +97,7 @@ angular.module('ngCookies', ['ng']). cookies[name] = value; } if (value !== lastCookies[name]) { - $browser.cookies(name, value); + $$cookieWriter(name, value); updated = true; } } @@ -105,7 +105,7 @@ angular.module('ngCookies', ['ng']). //verify what was actually stored if (updated) { updated = false; - browserCookies = $browser.cookies(); + browserCookies = $$cookieReader(); for (name in cookies) { if (cookies[name] !== browserCookies[name]) { diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index dcefe12008ca..ca4e271cd181 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -59,8 +59,6 @@ angular.mock.$Browser = function() { self.$$checkUrlChange = angular.noop; - self.cookieHash = {}; - self.lastCookieHash = {}; self.deferredFns = []; self.deferredNextId = 0; @@ -163,25 +161,6 @@ angular.mock.$Browser.prototype = { return this.$$state; }, - cookies: function(name, value) { - if (name) { - if (angular.isUndefined(value)) { - delete this.cookieHash[name]; - } else { - if (angular.isString(value) && //strings only - value.length <= 4096) { //strict cookie storage limits - this.cookieHash[name] = value; - } - } - } else { - if (!angular.equals(this.cookieHash, this.lastCookieHash)) { - this.lastCookieHash = angular.copy(this.cookieHash); - this.cookieHash = angular.copy(this.cookieHash); - } - return this.cookieHash; - } - }, - notifyWhenNoOutstandingRequests: function(fn) { fn(); } diff --git a/test/ng/browserSpecs.js b/test/ng/browserSpecs.js index 65321c24a499..fa7d8686d915 100755 --- a/test/ng/browserSpecs.js +++ b/test/ng/browserSpecs.js @@ -189,10 +189,6 @@ describe('browser', function() { } }); - it('should contain cookie cruncher', function() { - expect(browser.cookies).toBeDefined(); - }); - describe('outstading requests', function() { it('should process callbacks immedietly with no outstanding requests', function() { var callback = jasmine.createSpy('callback'); @@ -253,217 +249,6 @@ describe('browser', function() { }); - describe('cookies', function() { - - function deleteAllCookies() { - var cookies = document.cookie.split(";"); - var path = location.pathname; - - for (var i = 0; i < cookies.length; i++) { - var cookie = cookies[i]; - var eqPos = cookie.indexOf("="); - var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie; - var parts = path.split('/'); - while (parts.length) { - document.cookie = name + "=;path=" + (parts.join('/') || '/') + ";expires=Thu, 01 Jan 1970 00:00:00 GMT"; - parts.pop(); - } - } - } - - beforeEach(function() { - deleteAllCookies(); - expect(document.cookie).toEqual(''); - }); - - - afterEach(function() { - deleteAllCookies(); - expect(document.cookie).toEqual(''); - }); - - - describe('remove all via (null)', function() { - - it('should do nothing when no cookies are set', function() { - browser.cookies(null); - expect(document.cookie).toEqual(''); - expect(browser.cookies()).toEqual({}); - }); - - }); - - describe('remove via cookies(cookieName, undefined)', function() { - - it('should remove a cookie when it is present', function() { - document.cookie = 'foo=bar;path=/'; - - browser.cookies('foo', undefined); - - expect(document.cookie).toEqual(''); - expect(browser.cookies()).toEqual({}); - }); - - - it('should do nothing when an nonexisting cookie is being removed', function() { - browser.cookies('doesntexist', undefined); - expect(document.cookie).toEqual(''); - expect(browser.cookies()).toEqual({}); - }); - }); - - - describe('put via cookies(cookieName, string)', function() { - - it('should create and store a cookie', function() { - browser.cookies('cookieName', 'cookie=Value'); - expect(document.cookie).toMatch(/cookieName=cookie%3DValue;? ?/); - expect(browser.cookies()).toEqual({'cookieName':'cookie=Value'}); - }); - - - it('should overwrite an existing unsynced cookie', function() { - document.cookie = "cookie=new;path=/"; - - var oldVal = browser.cookies('cookie', 'newer'); - - expect(document.cookie).toEqual('cookie=newer'); - expect(browser.cookies()).toEqual({'cookie':'newer'}); - expect(oldVal).not.toBeDefined(); - }); - - it('should encode both name and value', function() { - browser.cookies('cookie1=', 'val;ue'); - browser.cookies('cookie2=bar;baz', 'val=ue'); - - var rawCookies = document.cookie.split("; "); //order is not guaranteed, so we need to parse - expect(rawCookies.length).toEqual(2); - expect(rawCookies).toContain('cookie1%3D=val%3Bue'); - expect(rawCookies).toContain('cookie2%3Dbar%3Bbaz=val%3Due'); - }); - - it('should log warnings when 4kb per cookie storage limit is reached', function() { - var i, longVal = '', cookieStr; - - for (i = 0; i < 4083; i++) { - longVal += 'x'; - } - - cookieStr = document.cookie; - browser.cookies('x', longVal); //total size 4093-4096, so it should go through - expect(document.cookie).not.toEqual(cookieStr); - expect(browser.cookies()['x']).toEqual(longVal); - expect(logs.warn).toEqual([]); - - browser.cookies('x', longVal + 'xxxx'); //total size 4097-4099, a warning should be logged - expect(logs.warn).toEqual( - [["Cookie 'x' possibly not set or overflowed because it was too large (4097 > 4096 " + - "bytes)!"]]); - - //force browser to dropped a cookie and make sure that the cache is not out of sync - browser.cookies('x', 'shortVal'); - expect(browser.cookies().x).toEqual('shortVal'); //needed to prime the cache - cookieStr = document.cookie; - browser.cookies('x', longVal + longVal + longVal); //should be too long for all browsers - - if (document.cookie !== cookieStr) { - this.fail(new Error("browser didn't drop long cookie when it was expected. make the " + - "cookie in this test longer")); - } - - expect(browser.cookies().x).toEqual('shortVal'); - }); - }); - - describe('put via cookies(cookieName, string), if no ', function() { - beforeEach(function() { - fakeDocument.basePath = undefined; - }); - - it('should default path in cookie to "" (empty string)', function() { - browser.cookies('cookie', 'bender'); - // This only fails in Safari and IE when cookiePath returns undefined - // Where it now succeeds since baseHref return '' instead of undefined - expect(document.cookie).toEqual('cookie=bender'); - }); - }); - - describe('get via cookies()[cookieName]', function() { - - it('should return undefined for nonexistent cookie', function() { - expect(browser.cookies().nonexistent).not.toBeDefined(); - }); - - - it('should return a value for an existing cookie', function() { - document.cookie = "foo=bar=baz;path=/"; - expect(browser.cookies().foo).toEqual('bar=baz'); - }); - - it('should return the the first value provided for a cookie', function() { - // For a cookie that has different values that differ by path, the - // value for the most specific path appears first. browser.cookies() - // should provide that value for the cookie. - document.cookie = 'foo="first"; foo="second"'; - expect(browser.cookies()['foo']).toBe('"first"'); - }); - - it('should decode cookie values that were encoded by puts', function() { - document.cookie = "cookie2%3Dbar%3Bbaz=val%3Due;path=/"; - expect(browser.cookies()['cookie2=bar;baz']).toEqual('val=ue'); - }); - - - it('should preserve leading & trailing spaces in names and values', function() { - browser.cookies(' cookie name ', ' cookie value '); - expect(browser.cookies()[' cookie name ']).toEqual(' cookie value '); - expect(browser.cookies()['cookie name']).not.toBeDefined(); - }); - - it('should decode special characters in cookie values', function() { - document.cookie = 'cookie_name=cookie_value_%E2%82%AC'; - expect(browser.cookies()['cookie_name']).toEqual('cookie_value_€'); - }); - - it('should not decode cookie values that do not appear to be encoded', function() { - // see #9211 - sometimes cookies contain a value that causes decodeURIComponent to throw - document.cookie = 'cookie_name=cookie_value_%XX'; - expect(browser.cookies()['cookie_name']).toEqual('cookie_value_%XX'); - }); - }); - - - describe('getAll via cookies()', function() { - - it('should return cookies as hash', function() { - document.cookie = "foo1=bar1;path=/"; - document.cookie = "foo2=bar2;path=/"; - expect(browser.cookies()).toEqual({'foo1':'bar1', 'foo2':'bar2'}); - }); - - - it('should return empty hash if no cookies exist', function() { - expect(browser.cookies()).toEqual({}); - }); - }); - - - it('should pick up external changes made to browser cookies', function() { - browser.cookies('oatmealCookie', 'drool'); - expect(browser.cookies()).toEqual({'oatmealCookie':'drool'}); - - document.cookie = 'oatmealCookie=changed;path=/'; - expect(browser.cookies().oatmealCookie).toEqual('changed'); - }); - - - it('should initialize cookie cache with existing cookies', function() { - document.cookie = "existingCookie=existingValue;path=/"; - expect(browser.cookies()).toEqual({'existingCookie':'existingValue'}); - }); - - }); - describe('poller', function() { it('should call functions in pollFns in regular intervals', function() { diff --git a/test/ng/cookieReaderSpec.js b/test/ng/cookieReaderSpec.js new file mode 100644 index 000000000000..e8756c4b5235 --- /dev/null +++ b/test/ng/cookieReaderSpec.js @@ -0,0 +1,103 @@ +'use strict'; + +describe('$$cookieReader', function() { + var $$cookieReader; + + function deleteAllCookies() { + var cookies = document.cookie.split(";"); + var path = location.pathname; + + for (var i = 0; i < cookies.length; i++) { + var cookie = cookies[i]; + var eqPos = cookie.indexOf("="); + var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie; + var parts = path.split('/'); + while (parts.length) { + document.cookie = name + "=;path=" + (parts.join('/') || '/') + ";expires=Thu, 01 Jan 1970 00:00:00 GMT"; + parts.pop(); + } + } + } + + beforeEach(function() { + deleteAllCookies(); + expect(document.cookie).toEqual(''); + + inject(function(_$$cookieReader_) { + $$cookieReader = _$$cookieReader_; + }); + }); + + + afterEach(function() { + deleteAllCookies(); + expect(document.cookie).toEqual(''); + }); + + + describe('get via $$cookieReader()[cookieName]', function() { + + it('should return undefined for nonexistent cookie', function() { + expect($$cookieReader().nonexistent).not.toBeDefined(); + }); + + + it('should return a value for an existing cookie', function() { + document.cookie = "foo=bar=baz;path=/"; + expect($$cookieReader().foo).toEqual('bar=baz'); + }); + + it('should return the the first value provided for a cookie', function() { + // For a cookie that has different values that differ by path, the + // value for the most specific path appears first. $$cookieReader() + // should provide that value for the cookie. + document.cookie = 'foo="first"; foo="second"'; + expect($$cookieReader()['foo']).toBe('"first"'); + }); + + it('should decode cookie values that were encoded by puts', function() { + document.cookie = "cookie2%3Dbar%3Bbaz=val%3Due;path=/"; + expect($$cookieReader()['cookie2=bar;baz']).toEqual('val=ue'); + }); + + + it('should preserve leading & trailing spaces in names and values', function() { + document.cookie = '%20cookie%20name%20=%20cookie%20value%20'; + expect($$cookieReader()[' cookie name ']).toEqual(' cookie value '); + expect($$cookieReader()['cookie name']).not.toBeDefined(); + }); + + it('should decode special characters in cookie values', function() { + document.cookie = 'cookie_name=cookie_value_%E2%82%AC'; + expect($$cookieReader()['cookie_name']).toEqual('cookie_value_€'); + }); + + it('should not decode cookie values that do not appear to be encoded', function() { + // see #9211 - sometimes cookies contain a value that causes decodeURIComponent to throw + document.cookie = 'cookie_name=cookie_value_%XX'; + expect($$cookieReader()['cookie_name']).toEqual('cookie_value_%XX'); + }); + }); + + + describe('getAll via $$cookieReader()', function() { + + it('should return cookies as hash', function() { + document.cookie = "foo1=bar1;path=/"; + document.cookie = "foo2=bar2;path=/"; + expect($$cookieReader()).toEqual({'foo1':'bar1', 'foo2':'bar2'}); + }); + + + it('should return empty hash if no cookies exist', function() { + expect($$cookieReader()).toEqual({}); + }); + }); + + + it('should initialize cookie cache with existing cookies', function() { + document.cookie = "existingCookie=existingValue;path=/"; + expect($$cookieReader()).toEqual({'existingCookie':'existingValue'}); + }); + +}); diff --git a/test/ng/httpSpec.js b/test/ng/httpSpec.js index 1a394f3e3fbf..dbb6290323ae 100644 --- a/test/ng/httpSpec.js +++ b/test/ng/httpSpec.js @@ -2,10 +2,16 @@ describe('$http', function() { - var callback; + var callback, mockedCookies; beforeEach(function() { callback = jasmine.createSpy('done'); + mockedCookies = {}; + module({ + $$cookieReader: function() { + return mockedCookies; + } + }); }); beforeEach(module(function($exceptionHandlerProvider) { @@ -691,7 +697,7 @@ describe('$http', function() { }); it('should not set XSRF cookie for cross-domain requests', inject(function($browser) { - $browser.cookies('XSRF-TOKEN', 'secret'); + mockedCookies['XSRF-TOKEN'] = 'secret'; $browser.url('http://host.com/base'); $httpBackend.expect('GET', 'http://www.test.com/url', undefined, function(headers) { return headers['X-XSRF-TOKEN'] === undefined; @@ -733,15 +739,15 @@ describe('$http', function() { $httpBackend.flush(); }); - it('should set the XSRF cookie into a XSRF header', inject(function($browser) { + it('should set the XSRF cookie into a XSRF header', inject(function() { function checkXSRF(secret, header) { return function(headers) { return headers[header || 'X-XSRF-TOKEN'] == secret; }; } - $browser.cookies('XSRF-TOKEN', 'secret'); - $browser.cookies('aCookie', 'secret2'); + mockedCookies['XSRF-TOKEN'] = 'secret'; + mockedCookies['aCookie'] = 'secret2'; $httpBackend.expect('GET', '/url', undefined, checkXSRF('secret')).respond(''); $httpBackend.expect('POST', '/url', undefined, checkXSRF('secret')).respond(''); $httpBackend.expect('PUT', '/url', undefined, checkXSRF('secret')).respond(''); @@ -809,23 +815,18 @@ describe('$http', function() { expect(config.foo).toBeUndefined(); }); - it('should check the cache before checking the XSRF cookie', inject(function($browser, $cacheFactory) { - var testCache = $cacheFactory('testCache'), - executionOrder = []; + it('should check the cache before checking the XSRF cookie', inject(function($cacheFactory) { + var testCache = $cacheFactory('testCache'); - spyOn($browser, 'cookies').andCallFake(function() { - executionOrder.push('cookies'); - return {'XSRF-TOKEN':'foo'}; - }); spyOn(testCache, 'get').andCallFake(function() { - executionOrder.push('cache'); + mockedCookies['XSRF-TOKEN'] = 'foo'; }); - $httpBackend.expect('GET', '/url', undefined).respond(''); + $httpBackend.expect('GET', '/url', undefined, function(headers) { + return headers['X-XSRF-TOKEN'] === 'foo'; + }).respond(''); $http({url: '/url', method: 'GET', cache: testCache}); $httpBackend.flush(); - - expect(executionOrder).toEqual(['cache', 'cookies']); })); }); diff --git a/test/ngCookies/cookieWriterSpec.js b/test/ngCookies/cookieWriterSpec.js new file mode 100644 index 000000000000..c3f0ce866c05 --- /dev/null +++ b/test/ngCookies/cookieWriterSpec.js @@ -0,0 +1,131 @@ +'use strict'; + +describe('$$cookieWriter', function() { + var $$cookieWriter; + + function deleteAllCookies() { + var cookies = document.cookie.split(";"); + var path = location.pathname; + + for (var i = 0; i < cookies.length; i++) { + var cookie = cookies[i]; + var eqPos = cookie.indexOf("="); + var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie; + var parts = path.split('/'); + while (parts.length) { + document.cookie = name + "=;path=" + (parts.join('/') || '/') + ";expires=Thu, 01 Jan 1970 00:00:00 GMT"; + parts.pop(); + } + } + } + + beforeEach(function() { + deleteAllCookies(); + expect(document.cookie).toEqual(''); + + module('ngCookies'); + inject(function(_$$cookieWriter_) { + $$cookieWriter = _$$cookieWriter_; + }); + }); + + + afterEach(function() { + deleteAllCookies(); + expect(document.cookie).toEqual(''); + }); + + + describe('remove via $$cookieWriter(cookieName, undefined)', function() { + + it('should remove a cookie when it is present', function() { + document.cookie = 'foo=bar;path=/'; + + $$cookieWriter('foo', undefined); + + expect(document.cookie).toEqual(''); + }); + + + it('should do nothing when an nonexisting cookie is being removed', function() { + $$cookieWriter('doesntexist', undefined); + expect(document.cookie).toEqual(''); + }); + }); + + + describe('put via $$cookieWriter(cookieName, string)', function() { + + it('should create and store a cookie', function() { + $$cookieWriter('cookieName', 'cookie=Value'); + expect(document.cookie).toMatch(/cookieName=cookie%3DValue;? ?/); + }); + + + it('should overwrite an existing unsynced cookie', function() { + document.cookie = "cookie=new;path=/"; + + var oldVal = $$cookieWriter('cookie', 'newer'); + + expect(document.cookie).toEqual('cookie=newer'); + expect(oldVal).not.toBeDefined(); + }); + + it('should encode both name and value', function() { + $$cookieWriter('cookie1=', 'val;ue'); + $$cookieWriter('cookie2=bar;baz', 'val=ue'); + + var rawCookies = document.cookie.split("; "); //order is not guaranteed, so we need to parse + expect(rawCookies.length).toEqual(2); + expect(rawCookies).toContain('cookie1%3D=val%3Bue'); + expect(rawCookies).toContain('cookie2%3Dbar%3Bbaz=val%3Due'); + }); + + it('should log warnings when 4kb per cookie storage limit is reached', inject(function($log) { + var i, longVal = '', cookieStr; + + for (i = 0; i < 4083; i++) { + longVal += 'x'; + } + + cookieStr = document.cookie; + $$cookieWriter('x', longVal); //total size 4093-4096, so it should go through + expect(document.cookie).not.toEqual(cookieStr); + expect(document.cookie).toEqual('x=' + longVal); + expect($log.warn.logs).toEqual([]); + + $$cookieWriter('x', longVal + 'xxxx'); //total size 4097-4099, a warning should be logged + expect($log.warn.logs).toEqual( + [["Cookie 'x' possibly not set or overflowed because it was too large (4097 > 4096 " + + "bytes)!"]]); + + //force browser to dropped a cookie and make sure that the cache is not out of sync + $$cookieWriter('x', 'shortVal'); + expect(document.cookie).toEqual('x=shortVal'); //needed to prime the cache + cookieStr = document.cookie; + $$cookieWriter('x', longVal + longVal + longVal); //should be too long for all browsers + + if (document.cookie !== cookieStr) { + this.fail(new Error("browser didn't drop long cookie when it was expected. make the " + + "cookie in this test longer")); + } + + expect(document.cookie).toEqual('x=shortVal'); + $log.reset(); + })); + }); + + describe('put via $$cookieWriter(cookieName, string), if no ', function() { + beforeEach(inject(function($browser) { + $browser.$$baseHref = undefined; + })); + + it('should default path in cookie to "" (empty string)', function() { + $$cookieWriter('cookie', 'bender'); + // This only fails in Safari and IE when cookiePath returns undefined + // Where it now succeeds since baseHref return '' instead of undefined + expect(document.cookie).toEqual('cookie=bender'); + }); + }); + +}); diff --git a/test/ngCookies/cookiesSpec.js b/test/ngCookies/cookiesSpec.js index 0a36c92f2aef..1d19221e1f7f 100644 --- a/test/ngCookies/cookiesSpec.js +++ b/test/ngCookies/cookiesSpec.js @@ -1,11 +1,24 @@ 'use strict'; describe('$cookies', function() { - beforeEach(module('ngCookies', function($provide) { - $provide.factory('$browser', function() { - return angular.extend(new angular.mock.$Browser(), {cookieHash: {preexisting:'oldCookie'}}); + var mockedCookies; + + beforeEach(function() { + var lastCookies = {}; + mockedCookies = {preexisting:'oldCookie'}; + module('ngCookies', { + $$cookieWriter: function(name, value) { + mockedCookies[name] = value; + }, + $$cookieReader: function() { + if (!angular.equals(lastCookies, mockedCookies)) { + lastCookies = angular.copy(mockedCookies); + mockedCookies = angular.copy(mockedCookies); + } + return mockedCookies; + } }); - })); + }); it('should provide access to existing cookies via object properties and keep them in sync', @@ -14,45 +27,45 @@ describe('$cookies', function() { // access internal cookie storage of the browser mock directly to simulate behavior of // document.cookie - $browser.cookieHash['brandNew'] = 'cookie'; + mockedCookies['brandNew'] = 'cookie'; $browser.poll(); expect($cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie'}); - $browser.cookieHash['brandNew'] = 'cookie2'; + mockedCookies['brandNew'] = 'cookie2'; $browser.poll(); expect($cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie2'}); - delete $browser.cookieHash['brandNew']; + delete mockedCookies['brandNew']; $browser.poll(); expect($cookies).toEqual({'preexisting': 'oldCookie'}); })); it('should create or update a cookie when a value is assigned to a property', - inject(function($cookies, $browser, $rootScope) { + inject(function($cookies, $$cookieReader, $rootScope) { $cookies.oatmealCookie = 'nom nom'; $rootScope.$digest(); - expect($browser.cookies()). + expect($$cookieReader()). toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'}); $cookies.oatmealCookie = 'gone'; $rootScope.$digest(); - expect($browser.cookies()). + expect($$cookieReader()). toEqual({'preexisting': 'oldCookie', 'oatmealCookie': 'gone'}); })); it('should convert non-string values to string', - inject(function($cookies, $browser, $rootScope) { + inject(function($cookies, $$cookieReader, $rootScope) { $cookies.nonString = [1, 2, 3]; $cookies.nullVal = null; $cookies.undefVal = undefined; var preexisting = $cookies.preexisting = function() {}; $rootScope.$digest(); - expect($browser.cookies()).toEqual({ + expect($$cookieReader()).toEqual({ 'preexisting': '' + preexisting, 'nonString': '1,2,3', 'nullVal': 'null', @@ -68,81 +81,73 @@ describe('$cookies', function() { it('should remove a cookie when a $cookies property is deleted', - inject(function($cookies, $browser, $rootScope) { + inject(function($cookies, $browser, $rootScope, $$cookieReader) { $cookies.oatmealCookie = 'nom nom'; $rootScope.$digest(); $browser.poll(); - expect($browser.cookies()). + expect($$cookieReader()). toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'}); delete $cookies.oatmealCookie; $rootScope.$digest(); - expect($browser.cookies()).toEqual({'preexisting': 'oldCookie'}); - })); - - - 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++) { - longVal += '*'; - } - - //drop if no previous value - $cookies.longCookie = longVal; - $rootScope.$digest(); - expect($cookies).toEqual({'preexisting': 'oldCookie'}); - - - //reset if previous value existed - $cookies.longCookie = 'shortVal'; - $rootScope.$digest(); - expect($cookies).toEqual({'preexisting': 'oldCookie', 'longCookie': 'shortVal'}); - $cookies.longCookie = longVal; - $rootScope.$digest(); - expect($cookies).toEqual({'preexisting': 'oldCookie', 'longCookie': 'shortVal'}); + expect($$cookieReader()).toEqual({'preexisting': 'oldCookie'}); })); }); describe('$cookieStore', function() { + var mockedCookies; + + beforeEach(function() { + var lastCookies = {}; + mockedCookies = {}; + module('ngCookies', { + $$cookieWriter: function(name, value) { + mockedCookies[name] = value; + }, + $$cookieReader: function() { + if (!angular.equals(lastCookies, mockedCookies)) { + lastCookies = angular.copy(mockedCookies); + mockedCookies = angular.copy(mockedCookies); + } + return mockedCookies; + } + }); + }); - beforeEach(module('ngCookies')); - - it('should serialize objects to json', inject(function($cookieStore, $browser, $rootScope) { + it('should serialize objects to json', inject(function($cookieStore, $$cookieReader, $rootScope) { $cookieStore.put('objectCookie', {id: 123, name: 'blah'}); $rootScope.$digest(); - expect($browser.cookies()).toEqual({'objectCookie': '{"id":123,"name":"blah"}'}); + expect($$cookieReader()).toEqual({'objectCookie': '{"id":123,"name":"blah"}'}); })); - it('should deserialize json to object', inject(function($cookieStore, $browser) { - $browser.cookies('objectCookie', '{"id":123,"name":"blah"}'); + it('should deserialize json to object', inject(function($cookieStore, $browser, $$cookieWriter) { + $$cookieWriter('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', inject(function($cookieStore, $browser, $rootScope) { + it('should delete objects from the store when remove is called', inject(function($cookieStore, $browser, $rootScope, $$cookieReader) { $cookieStore.put('gonner', { "I'll":"Be Back"}); $rootScope.$digest(); //force eval in test $browser.poll(); - expect($browser.cookies()).toEqual({'gonner': '{"I\'ll":"Be Back"}'}); + expect($$cookieReader()).toEqual({'gonner': '{"I\'ll":"Be Back"}'}); $cookieStore.remove('gonner'); $rootScope.$digest(); - expect($browser.cookies()).toEqual({}); + expect($$cookieReader()).toEqual({}); })); - it('should handle empty string value cookies', inject(function($cookieStore, $browser, $rootScope) { + it('should handle empty string value cookies', inject(function($cookieStore, $browser, $rootScope, $$cookieReader) { $cookieStore.put("emptyCookie",''); $rootScope.$digest(); - expect($browser.cookies()). + expect($$cookieReader()). toEqual({ 'emptyCookie': '""' }); expect($cookieStore.get("emptyCookie")).toEqual(''); - $browser.cookieHash['blankCookie'] = ''; + mockedCookies['blankCookie'] = ''; $browser.poll(); expect($cookieStore.get("blankCookie")).toEqual(''); })); From 011456fa7ff60fbb884bef7d55fd904d2a0d46f0 Mon Sep 17 00:00:00 2001 From: Shahar Talmi Date: Mon, 2 Mar 2015 13:42:21 +0200 Subject: [PATCH 067/489] refactor(ngCookies): split $cookies/$cookieStore to two files --- angularFiles.js | 1 + src/ngCookies/cookieStore.js | 76 +++++++++++++++++++++++++++++++ src/ngCookies/cookies.js | 75 ------------------------------ test/ngCookies/cookieStoreSpec.js | 58 +++++++++++++++++++++++ test/ngCookies/cookiesSpec.js | 58 ----------------------- 5 files changed, 135 insertions(+), 133 deletions(-) create mode 100644 src/ngCookies/cookieStore.js create mode 100644 test/ngCookies/cookieStoreSpec.js diff --git a/angularFiles.js b/angularFiles.js index 20bd1c3edded..7b8ac77b9b08 100755 --- a/angularFiles.js +++ b/angularFiles.js @@ -91,6 +91,7 @@ var angularFiles = { ], 'ngCookies': [ 'src/ngCookies/cookies.js', + 'src/ngCookies/cookieStore.js', 'src/ngCookies/cookieWriter.js' ], 'ngMessages': [ diff --git a/src/ngCookies/cookieStore.js b/src/ngCookies/cookieStore.js new file mode 100644 index 000000000000..62c9d790b37a --- /dev/null +++ b/src/ngCookies/cookieStore.js @@ -0,0 +1,76 @@ +'use strict'; + +angular.module('ngCookies'). +/** + * @ngdoc service + * @name $cookieStore + * @requires $cookies + * + * @description + * Provides a key-value (string-object) storage, that is backed by session cookies. + * Objects put or retrieved from this storage are automatically serialized or + * deserialized by angular's toJson/fromJson. + * + * Requires the {@link ngCookies `ngCookies`} module to be installed. + * + * @example + * + * ```js + * angular.module('cookieStoreExample', ['ngCookies']) + * .controller('ExampleController', ['$cookieStore', function($cookieStore) { + * // Put cookie + * $cookieStore.put('myFavorite','oatmeal'); + * // Get cookie + * var favoriteCookie = $cookieStore.get('myFavorite'); + * // Removing a cookie + * $cookieStore.remove('myFavorite'); + * }]); + * ``` + */ + factory('$cookieStore', ['$cookies', function($cookies) { + + return { + /** + * @ngdoc method + * @name $cookieStore#get + * + * @description + * Returns the value of given cookie key + * + * @param {string} key Id to use for lookup. + * @returns {Object} Deserialized cookie value, undefined if the cookie does not exist. + */ + get: function(key) { + var value = $cookies[key]; + return value ? angular.fromJson(value) : value; + }, + + /** + * @ngdoc method + * @name $cookieStore#put + * + * @description + * Sets a value for given cookie key + * + * @param {string} key Id for the `value`. + * @param {Object} value Value to be stored. + */ + put: function(key, value) { + $cookies[key] = angular.toJson(value); + }, + + /** + * @ngdoc method + * @name $cookieStore#remove + * + * @description + * Remove given cookie + * + * @param {string} key Id of the key-value pair to delete. + */ + remove: function(key) { + delete $cookies[key]; + } + }; + + }]); diff --git a/src/ngCookies/cookies.js b/src/ngCookies/cookies.js index d458243b25d1..3a49c4a3f8fa 100644 --- a/src/ngCookies/cookies.js +++ b/src/ngCookies/cookies.js @@ -120,79 +120,4 @@ angular.module('ngCookies', ['ng']). } } } - }]). - - - /** - * @ngdoc service - * @name $cookieStore - * @requires $cookies - * - * @description - * Provides a key-value (string-object) storage, that is backed by session cookies. - * Objects put or retrieved from this storage are automatically serialized or - * deserialized by angular's toJson/fromJson. - * - * Requires the {@link ngCookies `ngCookies`} module to be installed. - * - * @example - * - * ```js - * angular.module('cookieStoreExample', ['ngCookies']) - * .controller('ExampleController', ['$cookieStore', function($cookieStore) { - * // Put cookie - * $cookieStore.put('myFavorite','oatmeal'); - * // Get cookie - * var favoriteCookie = $cookieStore.get('myFavorite'); - * // Removing a cookie - * $cookieStore.remove('myFavorite'); - * }]); - * ``` - */ - factory('$cookieStore', ['$cookies', function($cookies) { - - return { - /** - * @ngdoc method - * @name $cookieStore#get - * - * @description - * Returns the value of given cookie key - * - * @param {string} key Id to use for lookup. - * @returns {Object} Deserialized cookie value, undefined if the cookie does not exist. - */ - get: function(key) { - var value = $cookies[key]; - return value ? angular.fromJson(value) : value; - }, - - /** - * @ngdoc method - * @name $cookieStore#put - * - * @description - * Sets a value for given cookie key - * - * @param {string} key Id for the `value`. - * @param {Object} value Value to be stored. - */ - put: function(key, value) { - $cookies[key] = angular.toJson(value); - }, - - /** - * @ngdoc method - * @name $cookieStore#remove - * - * @description - * Remove given cookie - * - * @param {string} key Id of the key-value pair to delete. - */ - remove: function(key) { - delete $cookies[key]; - } - }; - }]); diff --git a/test/ngCookies/cookieStoreSpec.js b/test/ngCookies/cookieStoreSpec.js new file mode 100644 index 000000000000..3a73afc5c2f4 --- /dev/null +++ b/test/ngCookies/cookieStoreSpec.js @@ -0,0 +1,58 @@ +'use strict'; + +describe('$cookieStore', function() { + var mockedCookies; + + beforeEach(function() { + var lastCookies = {}; + mockedCookies = {}; + module('ngCookies', { + $$cookieWriter: function(name, value) { + mockedCookies[name] = value; + }, + $$cookieReader: function() { + if (!angular.equals(lastCookies, mockedCookies)) { + lastCookies = angular.copy(mockedCookies); + mockedCookies = angular.copy(mockedCookies); + } + return mockedCookies; + } + }); + }); + + it('should serialize objects to json', inject(function($cookieStore, $$cookieReader, $rootScope) { + $cookieStore.put('objectCookie', {id: 123, name: 'blah'}); + $rootScope.$digest(); + expect($$cookieReader()).toEqual({'objectCookie': '{"id":123,"name":"blah"}'}); + })); + + + it('should deserialize json to object', inject(function($cookieStore, $browser, $$cookieWriter) { + $$cookieWriter('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', inject(function($cookieStore, $browser, $rootScope, $$cookieReader) { + $cookieStore.put('gonner', { "I'll":"Be Back"}); + $rootScope.$digest(); //force eval in test + $browser.poll(); + expect($$cookieReader()).toEqual({'gonner': '{"I\'ll":"Be Back"}'}); + + $cookieStore.remove('gonner'); + $rootScope.$digest(); + expect($$cookieReader()).toEqual({}); + })); + it('should handle empty string value cookies', inject(function($cookieStore, $browser, $rootScope, $$cookieReader) { + $cookieStore.put("emptyCookie",''); + $rootScope.$digest(); + expect($$cookieReader()). + toEqual({ 'emptyCookie': '""' }); + expect($cookieStore.get("emptyCookie")).toEqual(''); + + mockedCookies['blankCookie'] = ''; + $browser.poll(); + expect($cookieStore.get("blankCookie")).toEqual(''); + })); +}); diff --git a/test/ngCookies/cookiesSpec.js b/test/ngCookies/cookiesSpec.js index 1d19221e1f7f..be3cd306f5a6 100644 --- a/test/ngCookies/cookiesSpec.js +++ b/test/ngCookies/cookiesSpec.js @@ -94,61 +94,3 @@ describe('$cookies', function() { expect($$cookieReader()).toEqual({'preexisting': 'oldCookie'}); })); }); - - -describe('$cookieStore', function() { - var mockedCookies; - - beforeEach(function() { - var lastCookies = {}; - mockedCookies = {}; - module('ngCookies', { - $$cookieWriter: function(name, value) { - mockedCookies[name] = value; - }, - $$cookieReader: function() { - if (!angular.equals(lastCookies, mockedCookies)) { - lastCookies = angular.copy(mockedCookies); - mockedCookies = angular.copy(mockedCookies); - } - return mockedCookies; - } - }); - }); - - it('should serialize objects to json', inject(function($cookieStore, $$cookieReader, $rootScope) { - $cookieStore.put('objectCookie', {id: 123, name: 'blah'}); - $rootScope.$digest(); - expect($$cookieReader()).toEqual({'objectCookie': '{"id":123,"name":"blah"}'}); - })); - - - it('should deserialize json to object', inject(function($cookieStore, $browser, $$cookieWriter) { - $$cookieWriter('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', inject(function($cookieStore, $browser, $rootScope, $$cookieReader) { - $cookieStore.put('gonner', { "I'll":"Be Back"}); - $rootScope.$digest(); //force eval in test - $browser.poll(); - expect($$cookieReader()).toEqual({'gonner': '{"I\'ll":"Be Back"}'}); - - $cookieStore.remove('gonner'); - $rootScope.$digest(); - expect($$cookieReader()).toEqual({}); - })); - it('should handle empty string value cookies', inject(function($cookieStore, $browser, $rootScope, $$cookieReader) { - $cookieStore.put("emptyCookie",''); - $rootScope.$digest(); - expect($$cookieReader()). - toEqual({ 'emptyCookie': '""' }); - expect($cookieStore.get("emptyCookie")).toEqual(''); - - mockedCookies['blankCookie'] = ''; - $browser.poll(); - expect($cookieStore.get("blankCookie")).toEqual(''); - })); -}); From b5eecdc7157dfe360599d8f027a2c4f091c67935 Mon Sep 17 00:00:00 2001 From: Shahar Talmi Date: Mon, 2 Mar 2015 20:52:58 +0200 Subject: [PATCH 068/489] feat($cookies): move logic into $cookies and deprecate $cookieStore The new API on `$cookies` includes: * `get` * `put` * `getObject` * `putObject` * `getAll` * `remove` The new API no longer polls the browser for changes to the cookies and no longer copy cookie values onto the `$cookies` object. The polling is expensive and caused issues with the `$cookies` properties not synchronizing correctly with the actual browser cookie values. The reason the polling was originally added was to allow communication between different tabs, but there are better ways to do this today (for example `localStorage`). DEPRECATION NOTICE: `$cookieStore` is now deprecated as all the useful logic has been moved to `$cookies`, to which `$cookieStore` now simply delegates calls. BREAKING CHANGE: `$cookies` no longer exposes properties that represent the current browser cookie values. Now you must explicitly the methods described above to access the cookie values. This also means that you can no longer watch the `$cookies` properties for changes to the browser's cookies. This feature is generally only needed if a 3rd party library was programmatically changing the cookies at runtime. If you rely on this then you must either write code that can react to the 3rd party library making the changes to cookies or implement your own polling mechanism. Closes #6411 Closes #7631 --- src/ngCookies/cookieStore.js | 13 ++- src/ngCookies/cookies.js | 160 ++++++++++++++++-------------- test/ngCookies/cookieStoreSpec.js | 63 +++--------- test/ngCookies/cookiesSpec.js | 100 +++++++------------ 4 files changed, 145 insertions(+), 191 deletions(-) diff --git a/src/ngCookies/cookieStore.js b/src/ngCookies/cookieStore.js index 62c9d790b37a..76a141114303 100644 --- a/src/ngCookies/cookieStore.js +++ b/src/ngCookies/cookieStore.js @@ -4,6 +4,7 @@ angular.module('ngCookies'). /** * @ngdoc service * @name $cookieStore + * @deprecated * @requires $cookies * * @description @@ -13,6 +14,11 @@ angular.module('ngCookies'). * * Requires the {@link ngCookies `ngCookies`} module to be installed. * + *
+ * **Note:** The $cookieStore service is deprecated. + * Please use the {@link ngCookies.$cookies `$cookies`} service instead. + *
+ * * @example * * ```js @@ -41,8 +47,7 @@ angular.module('ngCookies'). * @returns {Object} Deserialized cookie value, undefined if the cookie does not exist. */ get: function(key) { - var value = $cookies[key]; - return value ? angular.fromJson(value) : value; + return $cookies.getObject(key); }, /** @@ -56,7 +61,7 @@ angular.module('ngCookies'). * @param {Object} value Value to be stored. */ put: function(key, value) { - $cookies[key] = angular.toJson(value); + $cookies.putObject(key, value); }, /** @@ -69,7 +74,7 @@ angular.module('ngCookies'). * @param {string} key Id of the key-value pair to delete. */ remove: function(key) { - delete $cookies[key]; + $cookies.remove(key); } }; diff --git a/src/ngCookies/cookies.js b/src/ngCookies/cookies.js index 3a49c4a3f8fa..47539067b422 100644 --- a/src/ngCookies/cookies.js +++ b/src/ngCookies/cookies.js @@ -25,9 +25,9 @@ angular.module('ngCookies', ['ng']). * @description * Provides read/write access to browser's cookies. * - * Only a simple Object is exposed and by adding or removing properties to/from this object, new - * cookies are created/deleted at the end of current $eval. - * The object's properties can only be strings. + * BREAKING CHANGE: `$cookies` no longer exposes properties that represent the + * current browser cookie values. Now you must use the get/put/remove/etc. methods + * as described below. * * Requires the {@link ngCookies `ngCookies`} module to be installed. * @@ -37,87 +37,95 @@ angular.module('ngCookies', ['ng']). * angular.module('cookiesExample', ['ngCookies']) * .controller('ExampleController', ['$cookies', function($cookies) { * // Retrieving a cookie - * var favoriteCookie = $cookies.myFavorite; + * var favoriteCookie = $cookies.get('myFavorite'); * // Setting a cookie - * $cookies.myFavorite = 'oatmeal'; + * $cookies.put('myFavorite', 'oatmeal'); * }]); * ``` */ - factory('$cookies', ['$rootScope', '$browser', '$$cookieReader', '$$cookieWriter', function($rootScope, $browser, $$cookieReader, $$cookieWriter) { - var cookies = {}, - lastCookies = {}, - lastBrowserCookies, - runEval = false, - copy = angular.copy, - isUndefined = angular.isUndefined; + factory('$cookies', ['$$cookieReader', '$$cookieWriter', function($$cookieReader, $$cookieWriter) { + return { + /** + * @ngdoc method + * @name $cookies#get + * + * @description + * Returns the value of given cookie key + * + * @param {string} key Id to use for lookup. + * @returns {string} Raw cookie value. + */ + get: function(key) { + return $$cookieReader()[key]; + }, - //creates a poller fn that copies all cookies from the $browser to service & inits the service - $browser.addPollFn(function() { - var currentCookies = $$cookieReader(); - if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl - lastBrowserCookies = currentCookies; - copy(currentCookies, lastCookies); - copy(currentCookies, cookies); - if (runEval) $rootScope.$apply(); - } - })(); - - runEval = true; - - //at the end of each eval, push cookies - //TODO: this should happen before the "delayed" watches fire, because if some cookies are not - // strings or browser refuses to store some cookies, we update the model in the push fn. - $rootScope.$watch(push); - - return cookies; + /** + * @ngdoc method + * @name $cookies#getObject + * + * @description + * Returns the deserialized value of given cookie key + * + * @param {string} key Id to use for lookup. + * @returns {Object} Deserialized cookie value. + */ + getObject: function(key) { + var value = $$cookieReader()[key]; + return value ? angular.fromJson(value) : value; + }, + /** + * @ngdoc method + * @name $cookies#getAll + * + * @description + * Returns a key value object with all the cookies + * + * @returns {Object} All cookies + */ + getAll: function() { + return $$cookieReader(); + }, - /** - * Pushes all the cookies from the service to the browser and verifies if all cookies were - * stored. - */ - function push() { - var name, - value, - browserCookies, - updated; - - //delete any cookies deleted in $cookies - for (name in lastCookies) { - if (isUndefined(cookies[name])) { - $$cookieWriter(name, undefined); - } - } - - //update all cookies updated in $cookies - for (name in cookies) { - value = cookies[name]; - if (!angular.isString(value)) { - value = '' + value; - cookies[name] = value; - } - if (value !== lastCookies[name]) { - $$cookieWriter(name, value); - updated = true; - } - } + /** + * @ngdoc method + * @name $cookies#put + * + * @description + * Sets a value for given cookie key + * + * @param {string} key Id for the `value`. + * @param {string} value Raw value to be stored. + */ + put: function(key, value) { + $$cookieWriter(key, value); + }, - //verify what was actually stored - if (updated) { - updated = false; - browserCookies = $$cookieReader(); + /** + * @ngdoc method + * @name $cookies#putObject + * + * @description + * Serializes and sets a value for given cookie key + * + * @param {string} key Id for the `value`. + * @param {Object} value Value to be stored. + */ + putObject: function(key, value) { + $$cookieWriter(key, angular.toJson(value)); + }, - for (name in cookies) { - if (cookies[name] !== browserCookies[name]) { - //delete or reset all cookies that the browser dropped from $cookies - if (isUndefined(browserCookies[name])) { - delete cookies[name]; - } else { - cookies[name] = browserCookies[name]; - } - updated = true; - } - } + /** + * @ngdoc method + * @name $cookies#remove + * + * @description + * Remove given cookie + * + * @param {string} key Id of the key-value pair to delete. + */ + remove: function(key) { + $$cookieWriter(key, undefined); } - } + }; }]); diff --git a/test/ngCookies/cookieStoreSpec.js b/test/ngCookies/cookieStoreSpec.js index 3a73afc5c2f4..20436761b9f3 100644 --- a/test/ngCookies/cookieStoreSpec.js +++ b/test/ngCookies/cookieStoreSpec.js @@ -1,58 +1,27 @@ 'use strict'; describe('$cookieStore', function() { - var mockedCookies; - - beforeEach(function() { - var lastCookies = {}; - mockedCookies = {}; - module('ngCookies', { - $$cookieWriter: function(name, value) { - mockedCookies[name] = value; - }, - $$cookieReader: function() { - if (!angular.equals(lastCookies, mockedCookies)) { - lastCookies = angular.copy(mockedCookies); - mockedCookies = angular.copy(mockedCookies); - } - return mockedCookies; - } - }); - }); - - it('should serialize objects to json', inject(function($cookieStore, $$cookieReader, $rootScope) { - $cookieStore.put('objectCookie', {id: 123, name: 'blah'}); - $rootScope.$digest(); - expect($$cookieReader()).toEqual({'objectCookie': '{"id":123,"name":"blah"}'}); + + beforeEach(module('ngCookies', { + $cookies: jasmine.createSpyObj('$cookies', ['getObject', 'putObject', 'remove']) })); - it('should deserialize json to object', inject(function($cookieStore, $browser, $$cookieWriter) { - $$cookieWriter('objectCookie', '{"id":123,"name":"blah"}'); - $browser.poll(); - expect($cookieStore.get('objectCookie')).toEqual({id: 123, name: 'blah'}); + it('should get cookie', inject(function($cookieStore, $cookies) { + $cookies.getObject.andReturn('value'); + expect($cookieStore.get('name')).toBe('value'); + expect($cookies.getObject).toHaveBeenCalledWith('name'); })); - it('should delete objects from the store when remove is called', inject(function($cookieStore, $browser, $rootScope, $$cookieReader) { - $cookieStore.put('gonner', { "I'll":"Be Back"}); - $rootScope.$digest(); //force eval in test - $browser.poll(); - expect($$cookieReader()).toEqual({'gonner': '{"I\'ll":"Be Back"}'}); - - $cookieStore.remove('gonner'); - $rootScope.$digest(); - expect($$cookieReader()).toEqual({}); + it('should put cookie', inject(function($cookieStore, $cookies) { + $cookieStore.put('name', 'value'); + expect($cookies.putObject).toHaveBeenCalledWith('name', 'value'); })); - it('should handle empty string value cookies', inject(function($cookieStore, $browser, $rootScope, $$cookieReader) { - $cookieStore.put("emptyCookie",''); - $rootScope.$digest(); - expect($$cookieReader()). - toEqual({ 'emptyCookie': '""' }); - expect($cookieStore.get("emptyCookie")).toEqual(''); - - mockedCookies['blankCookie'] = ''; - $browser.poll(); - expect($cookieStore.get("blankCookie")).toEqual(''); + + + it('should remove cookie', inject(function($cookieStore, $cookies) { + $cookieStore.remove('name'); + expect($cookies.remove).toHaveBeenCalledWith('name'); })); -}); + }); diff --git a/test/ngCookies/cookiesSpec.js b/test/ngCookies/cookiesSpec.js index be3cd306f5a6..9c4eda6ad43c 100644 --- a/test/ngCookies/cookiesSpec.js +++ b/test/ngCookies/cookiesSpec.js @@ -4,93 +4,65 @@ describe('$cookies', function() { var mockedCookies; beforeEach(function() { - var lastCookies = {}; - mockedCookies = {preexisting:'oldCookie'}; + mockedCookies = {}; module('ngCookies', { $$cookieWriter: function(name, value) { mockedCookies[name] = value; }, $$cookieReader: function() { - if (!angular.equals(lastCookies, mockedCookies)) { - lastCookies = angular.copy(mockedCookies); - mockedCookies = angular.copy(mockedCookies); - } return mockedCookies; } }); }); - it('should provide access to existing cookies via object properties and keep them in sync', - 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 - mockedCookies['brandNew'] = 'cookie'; - $browser.poll(); - - expect($cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie'}); + it('should serialize objects to json', inject(function($cookies) { + $cookies.putObject('objectCookie', {id: 123, name: 'blah'}); + expect($cookies.get('objectCookie')).toEqual('{"id":123,"name":"blah"}'); + })); - mockedCookies['brandNew'] = 'cookie2'; - $browser.poll(); - expect($cookies).toEqual({'preexisting': 'oldCookie', 'brandNew':'cookie2'}); - delete mockedCookies['brandNew']; - $browser.poll(); - expect($cookies).toEqual({'preexisting': 'oldCookie'}); + it('should deserialize json to object', inject(function($cookies) { + $cookies.put('objectCookie', '{"id":123,"name":"blah"}'); + expect($cookies.getObject('objectCookie')).toEqual({id: 123, name: 'blah'}); })); - it('should create or update a cookie when a value is assigned to a property', - inject(function($cookies, $$cookieReader, $rootScope) { - $cookies.oatmealCookie = 'nom nom'; - $rootScope.$digest(); - - expect($$cookieReader()). - toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'}); + it('should delete objects from the store when remove is called', inject(function($cookies) { + $cookies.putObject('gonner', { "I'll":"Be Back"}); + expect($cookies.get('gonner')).toEqual('{"I\'ll":"Be Back"}'); + $cookies.remove('gonner'); + expect($cookies.get('gonner')).toEqual(undefined); + })); - $cookies.oatmealCookie = 'gone'; - $rootScope.$digest(); - expect($$cookieReader()). - toEqual({'preexisting': 'oldCookie', 'oatmealCookie': 'gone'}); + it('should handle empty string value cookies', inject(function($cookies) { + $cookies.putObject("emptyCookie",''); + expect($cookies.get('emptyCookie')).toEqual('""'); + expect($cookies.getObject("emptyCookie")).toEqual(''); + mockedCookies['blankCookie'] = ''; + expect($cookies.getObject("blankCookie")).toEqual(''); })); - it('should convert non-string values to string', - inject(function($cookies, $$cookieReader, $rootScope) { - $cookies.nonString = [1, 2, 3]; - $cookies.nullVal = null; - $cookies.undefVal = undefined; - var preexisting = $cookies.preexisting = function() {}; - $rootScope.$digest(); - expect($$cookieReader()).toEqual({ - 'preexisting': '' + preexisting, - 'nonString': '1,2,3', - 'nullVal': 'null', - 'undefVal': 'undefined' - }); - expect($cookies).toEqual({ - 'preexisting': '' + preexisting, - 'nonString': '1,2,3', - 'nullVal': 'null', - 'undefVal': 'undefined' - }); + it('should put cookie value without serializing', inject(function($cookies) { + $cookies.put('name', 'value'); + $cookies.put('name2', '"value2"'); + expect($cookies.get('name')).toEqual('value'); + expect($cookies.getObject('name2')).toEqual('value2'); })); - it('should remove a cookie when a $cookies property is deleted', - inject(function($cookies, $browser, $rootScope, $$cookieReader) { - $cookies.oatmealCookie = 'nom nom'; - $rootScope.$digest(); - $browser.poll(); - expect($$cookieReader()). - toEqual({'preexisting': 'oldCookie', 'oatmealCookie':'nom nom'}); - - delete $cookies.oatmealCookie; - $rootScope.$digest(); + it('should get cookie value without deserializing', inject(function($cookies) { + $cookies.put('name', 'value'); + $cookies.putObject('name2', 'value2'); + expect($cookies.get('name')).toEqual('value'); + expect($cookies.get('name2')).toEqual('"value2"'); + })); - expect($$cookieReader()).toEqual({'preexisting': 'oldCookie'}); + it('should get all the cookies', inject(function($cookies) { + $cookies.put('name', 'value'); + $cookies.putObject('name2', 'value2'); + expect($cookies.getAll()).toEqual({name: 'value', name2: '"value2"'}); })); -}); + }); From a10e240a09927b58c2153386c3941f6dbd3c6095 Mon Sep 17 00:00:00 2001 From: Shahar Talmi Date: Mon, 2 Mar 2015 21:46:51 +0200 Subject: [PATCH 069/489] feat($cookies): allow passing cookie options The `put`, `putObject` and `remove` methods now take an options parameter where you can provide additional options for the cookie value, such as `expires`, `path`, `domain` and `secure`. Closes #8324 Closes #3988 Closes #1786 Closes #950 --- src/ngCookies/cookieWriter.js | 52 +++++++++++++++-------- src/ngCookies/cookies.js | 25 ++++++++--- test/ngCookies/cookieWriterSpec.js | 67 ++++++++++++++++++++++++++++++ test/ngCookies/cookiesSpec.js | 22 +++++++++- 4 files changed, 140 insertions(+), 26 deletions(-) diff --git a/src/ngCookies/cookieWriter.js b/src/ngCookies/cookieWriter.js index 4cf714fbea50..b4f496f825bb 100644 --- a/src/ngCookies/cookieWriter.js +++ b/src/ngCookies/cookieWriter.js @@ -9,31 +9,47 @@ * * @param {string} name Cookie name * @param {string=} value Cookie value (if undefined, cookie will be deleted) + * @param {Object=} options Object with options that need to be stored for the cookie. */ function $$CookieWriter($document, $log, $browser) { var cookiePath = $browser.baseHref(); var rawDocument = $document[0]; - return function(name, value) { + function buildCookieString(name, value, options) { + var path, expires; + options = options || {}; + expires = options.expires; + path = angular.isDefined(options.path) ? options.path : cookiePath; if (value === undefined) { - rawDocument.cookie = encodeURIComponent(name) + "=;path=" + cookiePath + - ";expires=Thu, 01 Jan 1970 00:00:00 GMT"; - } else { - if (angular.isString(value)) { - var cookieLength = (rawDocument.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) + - ';path=' + cookiePath).length + 1; - - // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum: - // - 300 cookies - // - 20 cookies per unique domain - // - 4096 bytes per cookie - if (cookieLength > 4096) { - $log.warn("Cookie '" + name + - "' possibly not set or overflowed because it was too large (" + - cookieLength + " > 4096 bytes)!"); - } - } + expires = 'Thu, 01 Jan 1970 00:00:00 GMT'; + value = ''; } + if (angular.isString(expires)) { + expires = new Date(expires); + } + + var str = encodeURIComponent(name) + '=' + encodeURIComponent(value); + str += path ? ';path=' + path : ''; + str += options.domain ? ';domain=' + options.domain : ''; + str += expires ? ';expires=' + expires.toUTCString() : ''; + str += options.secure ? ';secure' : ''; + + // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum: + // - 300 cookies + // - 20 cookies per unique domain + // - 4096 bytes per cookie + var cookieLength = str.length + 1; + if (cookieLength > 4096) { + $log.warn("Cookie '" + name + + "' possibly not set or overflowed because it was too large (" + + cookieLength + " > 4096 bytes)!"); + } + + return str; + } + + return function(name, value, options) { + rawDocument.cookie = buildCookieString(name, value, options); }; } diff --git a/src/ngCookies/cookies.js b/src/ngCookies/cookies.js index 47539067b422..8164c4700f63 100644 --- a/src/ngCookies/cookies.js +++ b/src/ngCookies/cookies.js @@ -96,9 +96,20 @@ angular.module('ngCookies', ['ng']). * * @param {string} key Id for the `value`. * @param {string} value Raw value to be stored. + * @param {Object=} options Object with options that need to be stored for the cookie. + * The object may have following properties: + * + * - **path** - `{string}` - The cookie will be available only for this path and its + * sub-paths. By default, this would be the URL that appears in your base tag. + * - **domain** - `{string}` - The cookie will be available only for this domain and + * its sub-domains. For obvious security reasons the user agent will not accept the + * cookie if the current domain is not a sub domain or equals to the requested domain. + * - **expires** - `{string|Date}` - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT" + * or a Date object indicating the exact date/time this cookie will expire. + * - **secure** - `{boolean}` - The cookie will be available only in secured connection. */ - put: function(key, value) { - $$cookieWriter(key, value); + put: function(key, value, options) { + $$cookieWriter(key, value, options); }, /** @@ -110,9 +121,10 @@ angular.module('ngCookies', ['ng']). * * @param {string} key Id for the `value`. * @param {Object} value Value to be stored. + * @param {Object=} options Options object. */ - putObject: function(key, value) { - $$cookieWriter(key, angular.toJson(value)); + putObject: function(key, value, options) { + $$cookieWriter(key, angular.toJson(value), options); }, /** @@ -123,9 +135,10 @@ angular.module('ngCookies', ['ng']). * Remove given cookie * * @param {string} key Id of the key-value pair to delete. + * @param {Object=} options Options object. */ - remove: function(key) { - $$cookieWriter(key, undefined); + remove: function(key, options) { + $$cookieWriter(key, undefined, options); } }; }]); diff --git a/test/ngCookies/cookieWriterSpec.js b/test/ngCookies/cookieWriterSpec.js index c3f0ce866c05..e94f2b16e7c7 100644 --- a/test/ngCookies/cookieWriterSpec.js +++ b/test/ngCookies/cookieWriterSpec.js @@ -127,5 +127,72 @@ describe('$$cookieWriter', function() { expect(document.cookie).toEqual('cookie=bender'); }); }); +}); + +describe('cookie options', function() { + var fakeDocument, $$cookieWriter; + + function getLastCookieAssignment(key) { + return fakeDocument[0].cookie + .split(';') + .reduce(function(prev, value) { + var pair = value.split('=', 2); + if (pair[0] === key) { + if (prev === undefined) { + return pair[1] === undefined ? true : pair[1]; + } else { + throw 'duplicate key in cookie string'; + } + } else { + return prev; + } + }, undefined); + } + + beforeEach(function() { + fakeDocument = [{cookie: ''}]; + module('ngCookies', {$document: fakeDocument}); + inject(function($browser) { + $browser.$$baseHref = '/a/b'; + }); + inject(function(_$$cookieWriter_) { + $$cookieWriter = _$$cookieWriter_; + }); + }); + + it('should use baseHref as default path', function() { + $$cookieWriter('name', 'value'); + expect(getLastCookieAssignment('path')).toBe('/a/b'); + }); + + it('should accept path option', function() { + $$cookieWriter('name', 'value', {path: '/c/d'}); + expect(getLastCookieAssignment('path')).toBe('/c/d'); + }); + + it('should accept domain option', function() { + $$cookieWriter('name', 'value', {domain: '.example.com'}); + expect(getLastCookieAssignment('domain')).toBe('.example.com'); + }); + + it('should accept secure option', function() { + $$cookieWriter('name', 'value', {secure: true}); + expect(getLastCookieAssignment('secure')).toBe(true); + }); + + it('should accept expires option on set', function() { + $$cookieWriter('name', 'value', {expires: 'Fri, 19 Dec 2014 00:00:00 GMT'}); + expect(getLastCookieAssignment('expires')).toMatch(/^Fri, 19 Dec 2014 00:00:00 (UTC|GMT)$/); + }); + + it('should always use epoch time as expire time on remove', function() { + $$cookieWriter('name', undefined, {expires: 'Fri, 19 Dec 2014 00:00:00 GMT'}); + expect(getLastCookieAssignment('expires')).toMatch(/^Thu, 0?1 Jan 1970 00:00:00 (UTC|GMT)$/); + }); + + it('should accept date object as expires option', function() { + $$cookieWriter('name', 'value', {expires: new Date(Date.UTC(1981, 11, 27))}); + expect(getLastCookieAssignment('expires')).toMatch(/^Sun, 27 Dec 1981 00:00:00 (UTC|GMT)$/); + }); }); diff --git a/test/ngCookies/cookiesSpec.js b/test/ngCookies/cookiesSpec.js index 9c4eda6ad43c..bedfcf8697b2 100644 --- a/test/ngCookies/cookiesSpec.js +++ b/test/ngCookies/cookiesSpec.js @@ -6,9 +6,9 @@ describe('$cookies', function() { beforeEach(function() { mockedCookies = {}; module('ngCookies', { - $$cookieWriter: function(name, value) { + $$cookieWriter: jasmine.createSpy('$$cookieWriter').andCallFake(function(name, value) { mockedCookies[name] = value; - }, + }), $$cookieReader: function() { return mockedCookies; } @@ -65,4 +65,22 @@ describe('$cookies', function() { $cookies.putObject('name2', 'value2'); expect($cookies.getAll()).toEqual({name: 'value', name2: '"value2"'}); })); + + + it('should pass options on put', inject(function($cookies, $$cookieWriter) { + $cookies.put('name', 'value', {path: '/a/b'}); + expect($$cookieWriter).toHaveBeenCalledWith('name', 'value', {path: '/a/b'}); + })); + + + it('should pass options on putObject', inject(function($cookies, $$cookieWriter) { + $cookies.putObject('name', 'value', {path: '/a/b'}); + expect($$cookieWriter).toHaveBeenCalledWith('name', '"value"', {path: '/a/b'}); + })); + + + it('should pass options on remove', inject(function($cookies, $$cookieWriter) { + $cookies.remove('name', {path: '/a/b'}); + expect($$cookieWriter).toHaveBeenCalledWith('name', undefined, {path: '/a/b'}); + })); }); From ee1313c6074d596ec7d1f55734ab5101ca3e95d6 Mon Sep 17 00:00:00 2001 From: Shahar Talmi Date: Mon, 2 Mar 2015 22:08:04 +0200 Subject: [PATCH 070/489] feat($cookiesProvider): provide path, domain, expires and secure options This change provides properties on `$cookiesProvider` so that you can set the application level default options for cookies that are set using the `$cookies` service --- src/ngCookies/cookies.js | 109 +++++++++++++++++++++------------- test/ngCookies/cookiesSpec.js | 56 +++++++++++++++++ 2 files changed, 125 insertions(+), 40 deletions(-) diff --git a/src/ngCookies/cookies.js b/src/ngCookies/cookies.js index 8164c4700f63..bde93ce407e4 100644 --- a/src/ngCookies/cookies.js +++ b/src/ngCookies/cookies.js @@ -19,31 +19,66 @@ angular.module('ngCookies', ['ng']). /** - * @ngdoc service - * @name $cookies - * + * @ngdoc provider + * @name $cookiesProvider * @description - * Provides read/write access to browser's cookies. - * - * BREAKING CHANGE: `$cookies` no longer exposes properties that represent the - * current browser cookie values. Now you must use the get/put/remove/etc. methods - * as described below. - * - * Requires the {@link ngCookies `ngCookies`} module to be installed. - * - * @example - * - * ```js - * angular.module('cookiesExample', ['ngCookies']) - * .controller('ExampleController', ['$cookies', function($cookies) { - * // Retrieving a cookie - * var favoriteCookie = $cookies.get('myFavorite'); - * // Setting a cookie - * $cookies.put('myFavorite', 'oatmeal'); - * }]); - * ``` - */ - factory('$cookies', ['$$cookieReader', '$$cookieWriter', function($$cookieReader, $$cookieWriter) { + * Use `$cookiesProvider` to change the default behavior of the {@link ngCookies.$cookies $cookies} service. + * */ + provider('$cookies', [function $CookiesProvider() { + /** + * @ngdoc property + * @name $cookiesProvider#defaults + * @description + * + * Object containing default options to pass when setting cookies. + * + * The object may have following properties: + * + * - **path** - `{string}` - The cookie will be available only for this path and its + * sub-paths. By default, this would be the URL that appears in your base tag. + * - **domain** - `{string}` - The cookie will be available only for this domain and + * its sub-domains. For obvious security reasons the user agent will not accept the + * cookie if the current domain is not a sub domain or equals to the requested domain. + * - **expires** - `{string|Date}` - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT" + * or a Date object indicating the exact date/time this cookie will expire. + * - **secure** - `{boolean}` - The cookie will be available only in secured connection. + * + * Note: by default the address that appears in your tag will be used as path. + * This is import so that cookies will be visible for all routes in case html5mode is enabled + * + **/ + var defaults = this.defaults = {}; + + function calcOptions(options) { + return options ? angular.extend({}, defaults, options) : defaults; + } + + /** + * @ngdoc service + * @name $cookies + * + * @description + * Provides read/write access to browser's cookies. + * + * BREAKING CHANGE: `$cookies` no longer exposes properties that represent the + * current browser cookie values. Now you must use the get/put/remove/etc. methods + * as described below. + * + * Requires the {@link ngCookies `ngCookies`} module to be installed. + * + * @example + * + * ```js + * angular.module('cookiesExample', ['ngCookies']) + * .controller('ExampleController', ['$cookies', function($cookies) { + * // Retrieving a cookie + * var favoriteCookie = $cookies.get('myFavorite'); + * // Setting a cookie + * $cookies.put('myFavorite', 'oatmeal'); + * }]); + * ``` + */ + this.$get = ['$$cookieReader', '$$cookieWriter', function($$cookieReader, $$cookieWriter) { return { /** * @ngdoc method @@ -70,7 +105,7 @@ angular.module('ngCookies', ['ng']). * @returns {Object} Deserialized cookie value. */ getObject: function(key) { - var value = $$cookieReader()[key]; + var value = this.get(key); return value ? angular.fromJson(value) : value; }, @@ -96,20 +131,11 @@ angular.module('ngCookies', ['ng']). * * @param {string} key Id for the `value`. * @param {string} value Raw value to be stored. - * @param {Object=} options Object with options that need to be stored for the cookie. - * The object may have following properties: - * - * - **path** - `{string}` - The cookie will be available only for this path and its - * sub-paths. By default, this would be the URL that appears in your base tag. - * - **domain** - `{string}` - The cookie will be available only for this domain and - * its sub-domains. For obvious security reasons the user agent will not accept the - * cookie if the current domain is not a sub domain or equals to the requested domain. - * - **expires** - `{string|Date}` - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT" - * or a Date object indicating the exact date/time this cookie will expire. - * - **secure** - `{boolean}` - The cookie will be available only in secured connection. + * @param {Object=} options Options object. + * See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults} */ put: function(key, value, options) { - $$cookieWriter(key, value, options); + $$cookieWriter(key, value, calcOptions(options)); }, /** @@ -122,9 +148,10 @@ angular.module('ngCookies', ['ng']). * @param {string} key Id for the `value`. * @param {Object} value Value to be stored. * @param {Object=} options Options object. + * See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults} */ putObject: function(key, value, options) { - $$cookieWriter(key, angular.toJson(value), options); + this.put(key, angular.toJson(value), options); }, /** @@ -136,9 +163,11 @@ angular.module('ngCookies', ['ng']). * * @param {string} key Id of the key-value pair to delete. * @param {Object=} options Options object. + * See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults} */ remove: function(key, options) { - $$cookieWriter(key, undefined, options); + $$cookieWriter(key, undefined, calcOptions(options)); } }; - }]); + }]; + }]); diff --git a/test/ngCookies/cookiesSpec.js b/test/ngCookies/cookiesSpec.js index bedfcf8697b2..0fff36178d8b 100644 --- a/test/ngCookies/cookiesSpec.js +++ b/test/ngCookies/cookiesSpec.js @@ -83,4 +83,60 @@ describe('$cookies', function() { $cookies.remove('name', {path: '/a/b'}); expect($$cookieWriter).toHaveBeenCalledWith('name', undefined, {path: '/a/b'}); })); + + + it('should pass default options on put', function() { + module(function($cookiesProvider) { + $cookiesProvider.defaults.secure = true; + }); + inject(function($cookies, $$cookieWriter) { + $cookies.put('name', 'value', {path: '/a/b'}); + expect($$cookieWriter).toHaveBeenCalledWith('name', 'value', {path: '/a/b', secure: true}); + }); + }); + + + it('should pass default options on putObject', function() { + module(function($cookiesProvider) { + $cookiesProvider.defaults.secure = true; + }); + inject(function($cookies, $$cookieWriter) { + $cookies.putObject('name', 'value', {path: '/a/b'}); + expect($$cookieWriter).toHaveBeenCalledWith('name', '"value"', {path: '/a/b', secure: true}); + }); + }); + + + it('should pass default options on remove', function() { + module(function($cookiesProvider) { + $cookiesProvider.defaults.secure = true; + }); + inject(function($cookies, $$cookieWriter) { + $cookies.remove('name', {path: '/a/b'}); + expect($$cookieWriter).toHaveBeenCalledWith('name', undefined, {path: '/a/b', secure: true}); + }); + }); + + + it('should let passed options override default options', function() { + module(function($cookiesProvider) { + $cookiesProvider.defaults.secure = true; + }); + inject(function($cookies, $$cookieWriter) { + $cookies.put('name', 'value', {secure: false}); + expect($$cookieWriter).toHaveBeenCalledWith('name', 'value', {secure: false}); + }); + }); + + + it('should pass default options if no options are passed', function() { + module(function($cookiesProvider) { + $cookiesProvider.defaults.secure = true; + }); + inject(function($cookies, $$cookieWriter) { + $cookies.put('name', 'value'); + expect($$cookieWriter).toHaveBeenCalledWith('name', 'value', {secure: true}); + }); + }); + }); From 8d7f01ca041d97a351e430915b44197d6244cf67 Mon Sep 17 00:00:00 2001 From: Shahar Talmi Date: Mon, 2 Mar 2015 22:16:52 +0200 Subject: [PATCH 071/489] refactor($browser): remove private polling mechanism The only feature of Angular using this mechanism was `$cookies`, which no longer mirrors the browser cookie values and so does not need to poll. Closes #11222 --- src/ng/browser.js | 43 ------------------------------------- src/ngMock/angular-mocks.js | 6 ------ test/ng/browserSpecs.js | 33 ---------------------------- test/ng/locationSpec.js | 1 - 4 files changed, 83 deletions(-) diff --git a/src/ng/browser.js b/src/ng/browser.js index 179f060ed019..dc8d691d5872 100644 --- a/src/ng/browser.js +++ b/src/ng/browser.js @@ -73,11 +73,6 @@ function Browser(window, document, $log, $sniffer) { * @param {function()} callback Function that will be called when no outstanding request */ self.notifyWhenNoOutstandingRequests = function(callback) { - // force browser to execute all pollFns - this is needed so that cookies and other pollers fire - // at some deterministic time in respect to the test runner's actions. Leaving things up to the - // regular poller would result in flaky tests. - forEach(pollFns, function(pollFn) { pollFn(); }); - if (outstandingRequestCount === 0) { callback(); } else { @@ -85,44 +80,6 @@ function Browser(window, document, $log, $sniffer) { } }; - ////////////////////////////////////////////////////////////// - // Poll Watcher API - ////////////////////////////////////////////////////////////// - var pollFns = [], - pollTimeout; - - /** - * @name $browser#addPollFn - * - * @param {function()} fn Poll function to add - * - * @description - * Adds a function to the list of functions that poller periodically executes, - * and starts polling if not started yet. - * - * @returns {function()} the added function - */ - self.addPollFn = function(fn) { - if (isUndefined(pollTimeout)) startPoller(100, setTimeout); - pollFns.push(fn); - return fn; - }; - - /** - * @param {number} interval How often should browser call poll functions (ms) - * @param {function()} setTimeout Reference to a real or fake `setTimeout` function. - * - * @description - * Configures the poller to run in the specified intervals, using the specified - * setTimeout fn and kicks it off. - */ - function startPoller(interval, setTimeout) { - (function check() { - forEach(pollFns, function(pollFn) { pollFn(); }); - pollTimeout = setTimeout(check, interval); - })(); - } - ////////////////////////////////////////////////////////////// // URL API ////////////////////////////////////////////////////////////// diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index ca4e271cd181..1b8be7d77b96 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -138,11 +138,6 @@ angular.mock.$Browser.prototype = { }); }, - addPollFn: function(pollFn) { - this.pollFns.push(pollFn); - return pollFn; - }, - url: function(url, replace, state) { if (angular.isUndefined(state)) { state = null; @@ -2148,7 +2143,6 @@ if (window.jasmine || window.mocha) { if (injector) { injector.get('$rootElement').off(); - injector.get('$browser').pollFns.length = 0; } // clean up jquery's fragment cache diff --git a/test/ng/browserSpecs.js b/test/ng/browserSpecs.js index fa7d8686d915..3166a08a3599 100755 --- a/test/ng/browserSpecs.js +++ b/test/ng/browserSpecs.js @@ -249,37 +249,6 @@ describe('browser', function() { }); - describe('poller', function() { - - it('should call functions in pollFns in regular intervals', function() { - var log = ''; - browser.addPollFn(function() {log+='a';}); - browser.addPollFn(function() {log+='b';}); - expect(log).toEqual(''); - fakeWindow.setTimeout.flush(); - expect(log).toEqual('ab'); - fakeWindow.setTimeout.flush(); - expect(log).toEqual('abab'); - }); - - it('should startPoller', function() { - expect(fakeWindow.timeouts.length).toEqual(0); - - browser.addPollFn(function() {}); - expect(fakeWindow.timeouts.length).toEqual(1); - - //should remain 1 as it is the check fn - browser.addPollFn(function() {}); - expect(fakeWindow.timeouts.length).toEqual(1); - }); - - it('should return fn that was passed into addPollFn', function() { - var fn = function() { return 1; }; - var returnedFn = browser.addPollFn(fn); - expect(returnedFn).toBe(fn); - }); - }); - describe('url', function() { var pushState, replaceState, locationReplace; @@ -723,7 +692,6 @@ describe('browser', function() { fakeWindow.location.href = newUrl; }); $provide.value('$browser', browser); - browser.pollFns = []; sniffer.history = options.history; $provide.value('$sniffer', sniffer); @@ -846,7 +814,6 @@ describe('browser', function() { beforeEach(module(function($provide, $locationProvider) { $provide.value('$browser', browser); - browser.pollFns = []; })); it('should not interfere with legacy browser url replace behavior', function() { diff --git a/test/ng/locationSpec.js b/test/ng/locationSpec.js index de0561d0c16f..bbeef29f88e6 100644 --- a/test/ng/locationSpec.js +++ b/test/ng/locationSpec.js @@ -99,7 +99,6 @@ describe('$location', function() { /* global Browser: false */ var b = new Browser($window, $document, fakeLog, sniffer); - b.pollFns = []; return b; }; }); From 6aaef90f09ee69ad51a49212dc99ab53e2c39fe8 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Mon, 2 Mar 2015 22:34:31 +0000 Subject: [PATCH 072/489] docs(*): The Bootstrap CSS class `alert-error` is now `alert-danger` --- src/ng/compile.js | 4 ++-- src/ng/directive/ngInit.js | 2 +- src/ngCookies/cookieStore.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index f97c780d7061..7a5869e2d407 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -346,7 +346,7 @@ * `templateUrl` declaration or manual compilation inside the compile function. *
* - *
+ *
* **Note:** The `transclude` function that is passed to the compile function is deprecated, as it * e.g. does not know about the right outer scope. Please use the transclude function that is passed * to the link function instead. @@ -625,7 +625,7 @@ * @param {string|DOMElement} element Element or HTML string to compile into a template function. * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED. * - *
+ *
* **Note:** Passing a `transclude` function to the $compile function is deprecated, as it * e.g. will not use the right outer scope. Please pass the transclude function as a * `parentBoundTranscludeFn` to the link function instead. diff --git a/src/ng/directive/ngInit.js b/src/ng/directive/ngInit.js index 44b76856f4e7..37fc51f3d7f9 100644 --- a/src/ng/directive/ngInit.js +++ b/src/ng/directive/ngInit.js @@ -9,7 +9,7 @@ * The `ngInit` directive allows you to evaluate an expression in the * current scope. * - *
+ *
* The only appropriate use of `ngInit` is for aliasing special properties of * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you * should use {@link guide/controller controllers} rather than `ngInit` diff --git a/src/ngCookies/cookieStore.js b/src/ngCookies/cookieStore.js index 76a141114303..503fe5682642 100644 --- a/src/ngCookies/cookieStore.js +++ b/src/ngCookies/cookieStore.js @@ -14,7 +14,7 @@ angular.module('ngCookies'). * * Requires the {@link ngCookies `ngCookies`} module to be installed. * - *
+ *
* **Note:** The $cookieStore service is deprecated. * Please use the {@link ngCookies.$cookies `$cookies`} service instead. *
From b7a922afe569460948f1c2ac758ae0e3d612e199 Mon Sep 17 00:00:00 2001 From: "Martin R. Hufsky" Date: Mon, 22 Dec 2014 09:53:48 +0100 Subject: [PATCH 073/489] feat(filterFilter): compare object with custom `toString()` to primitive Closes #10464 Closes #10548 --- src/ng/filter/filter.js | 11 +++++++++-- test/ng/filter/filterSpec.js | 23 +++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/ng/filter/filter.js b/src/ng/filter/filter.js index 302e4ddabb27..3b6b444d3375 100644 --- a/src/ng/filter/filter.js +++ b/src/ng/filter/filter.js @@ -54,6 +54,9 @@ * - `false|undefined`: A short hand for a function which will look for a substring match in case * insensitive way. * + * Primitive values are converted to strings. Objects are not compared against primitives, + * unless they have a custom `toString` method (e.g. `Date` objects). + * * @example @@ -156,6 +159,10 @@ function filterFilter() { }; } +function hasCustomToString(obj) { + return isFunction(obj.toString) && obj.toString !== Object.prototype.toString; +} + // Helper functions for `filterFilter` function createPredicateFn(expression, comparator, matchAgainstAnyProp) { var shouldMatchPrimitives = isObject(expression) && ('$' in expression); @@ -165,8 +172,8 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) { comparator = equals; } else if (!isFunction(comparator)) { comparator = function(actual, expected) { - if (isObject(actual) || isObject(expected)) { - // Prevent an object to be considered equal to a string like `'[object'` + if (isObject(expected) || (isObject(actual) && !hasCustomToString(actual))) { + // Should not compare primitives against objects, unless they have custom `toString` method return false; } diff --git a/test/ng/filter/filterSpec.js b/test/ng/filter/filterSpec.js index ab3b76e7a5c5..a46652b07635 100644 --- a/test/ng/filter/filterSpec.js +++ b/test/ng/filter/filterSpec.js @@ -472,6 +472,29 @@ describe('Filter: filter', function() { }); + it('should consider custom `toString()` in non-strict comparison', function() { + var obj = new Date(1970, 0); + var items = [{test: obj}]; + expect(filter(items, '1970').length).toBe(1); + expect(filter(items, 1970).length).toBe(1); + + obj = {}; + obj.toString = function() { return 'custom'; }; + items = [{test: obj}]; + expect(filter(items, 'custom').length).toBe(1); + }); + + + it('should not throw on missing `toString()` in non-strict comparison', function() { + var obj = Object.create(null); + var items = [{test: obj}]; + expect(function() { + filter(items, 'foo'); + }).not.toThrow(); + expect(filter(items, 'foo').length).toBe(0); + }); + + it('as equality when true', function() { var items = ['misko', 'adam', 'adamson']; var expr = 'adam'; From 4508c0b541da7c7b3f7e66ed8d569b805a2065a4 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Tue, 3 Mar 2015 14:13:13 +0000 Subject: [PATCH 074/489] test(filterFilter): improve tests related to custom `toString` --- test/ng/filter/filterSpec.js | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/test/ng/filter/filterSpec.js b/test/ng/filter/filterSpec.js index a46652b07635..217ad25c5f7f 100644 --- a/test/ng/filter/filterSpec.js +++ b/test/ng/filter/filterSpec.js @@ -465,27 +465,28 @@ describe('Filter: filter', function() { describe('should support comparator', function() { - it('not consider `object === "[object Object]"` in non-strict comparison', function() { + it('not consider objects without a custom `toString` in non-strict comparison', function() { var items = [{test: {}}]; var expr = '[object'; expect(filter(items, expr).length).toBe(0); }); - it('should consider custom `toString()` in non-strict comparison', function() { + it('should consider objects with custom `toString()` in non-strict comparison', function() { var obj = new Date(1970, 0); var items = [{test: obj}]; expect(filter(items, '1970').length).toBe(1); expect(filter(items, 1970).length).toBe(1); - obj = {}; - obj.toString = function() { return 'custom'; }; + obj = { + toString: function() { return 'custom'; } + }; items = [{test: obj}]; expect(filter(items, 'custom').length).toBe(1); }); - it('should not throw on missing `toString()` in non-strict comparison', function() { + it('should cope with objects that have no `toString()` in non-strict comparison', function() { var obj = Object.create(null); var items = [{test: obj}]; expect(function() { @@ -495,6 +496,18 @@ describe('Filter: filter', function() { }); + it('should cope with objects where `toString` is not a function in non-strict comparison', function() { + var obj = { + toString: 'moo' + }; + var items = [{test: obj}]; + expect(function() { + filter(items, 'foo'); + }).not.toThrow(); + expect(filter(items, 'foo').length).toBe(0); + }); + + it('as equality when true', function() { var items = ['misko', 'adam', 'adamson']; var expr = 'adam'; From 558b2b9c470fb453559a31d5b25260862b5aafbd Mon Sep 17 00:00:00 2001 From: Caitlin Potter Date: Thu, 18 Dec 2014 16:50:18 -0500 Subject: [PATCH 075/489] feat(angular.merge): provide an alternative to `angular.extend` that merges 'deeply' Closes #10507 Closes #10519 --- src/.jshintrc | 1 + src/Angular.js | 69 ++++++++++++++++++++++++++++++++++--------- src/AngularPublic.js | 1 + test/.jshintrc | 1 + test/AngularSpec.js | 70 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 14 deletions(-) diff --git a/src/.jshintrc b/src/.jshintrc index d0561483c9ad..897cfd9372bf 100644 --- a/src/.jshintrc +++ b/src/.jshintrc @@ -35,6 +35,7 @@ "extend": false, "toInt": false, "inherit": false, + "merge": false, "noop": false, "identity": false, "valueFn": false, diff --git a/src/Angular.js b/src/Angular.js index 2a12f4c8e538..842b7845823a 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -29,6 +29,7 @@ extend: true, toInt: true, inherit: true, + merge: true, noop: true, identity: true, valueFn: true, @@ -318,6 +319,31 @@ function setHashKey(obj, h) { } } + +function baseExtend(dst, objs, deep) { + var h = dst.$$hashKey; + + for (var i = 0, ii = objs.length; i < ii; ++i) { + var obj = objs[i]; + if (!isObject(obj) && !isFunction(obj)) continue; + var keys = Object.keys(obj); + for (var j = 0, jj = keys.length; j < jj; j++) { + var key = keys[j]; + var src = obj[key]; + + if (deep && isObject(src)) { + if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {}; + baseExtend(dst[key], [src], true); + } else { + dst[key] = src; + } + } + } + + setHashKey(dst, h); + return dst; +} + /** * @ngdoc function * @name angular.extend @@ -328,30 +354,45 @@ function setHashKey(obj, h) { * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s) * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`. - * Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy). + * + * **Note:** Keep in mind that `angular.extend` does not support recursive merge (deep copy). Use + * {@link angular.merge} for this. * * @param {Object} dst Destination object. * @param {...Object} src Source object(s). + * @param {boolean=} deep if the last parameter is set to `true`, objects are recursively merged + * (deep copy). Defaults to `false`. * @returns {Object} Reference to `dst`. */ function extend(dst) { - var h = dst.$$hashKey; + return baseExtend(dst, slice.call(arguments, 1), false); +} - for (var i = 1, ii = arguments.length; i < ii; i++) { - var obj = arguments[i]; - if (obj) { - var keys = Object.keys(obj); - for (var j = 0, jj = keys.length; j < jj; j++) { - var key = keys[j]; - dst[key] = obj[key]; - } - } - } - setHashKey(dst, h); - return dst; +/** +* @ngdoc function +* @name angular.merge +* @module ng +* @kind function +* +* @description +* Deeply extends the destination object `dst` by copying own enumerable properties from the `src` object(s) +* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so +* by passing an empty object as the target: `var object = angular.merge({}, object1, object2)`. +* +* Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source +* objects, performing a deep copy. +* +* @param {Object} dst Destination object. +* @param {...Object} src Source object(s). +* @returns {Object} Reference to `dst`. +*/ +function merge(dst) { + return baseExtend(dst, slice.call(arguments, 1), true); } + + function toInt(str) { return parseInt(str, 10); } diff --git a/src/AngularPublic.js b/src/AngularPublic.js index 31e8483ee6bf..3b7a644c923d 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -117,6 +117,7 @@ function publishExternalAPI(angular) { 'bootstrap': bootstrap, 'copy': copy, 'extend': extend, + 'merge': merge, 'equals': equals, 'element': jqLite, 'forEach': forEach, diff --git a/test/.jshintrc b/test/.jshintrc index 98c963364465..3216347a8b2b 100644 --- a/test/.jshintrc +++ b/test/.jshintrc @@ -30,6 +30,7 @@ "nextUid": false, "setHashKey": false, "extend": false, + "merge": false, "toInt": false, "inherit": false, "noop": false, diff --git a/test/AngularSpec.js b/test/AngularSpec.js index 5d1835401b15..e70e49b49d3b 100644 --- a/test/AngularSpec.js +++ b/test/AngularSpec.js @@ -382,6 +382,7 @@ describe('angular', function() { expect(hashKey(dst)).not.toEqual(hashKey(src)); }); + it('should retain the previous $$hashKey', function() { var src,dst,h; src = {}; @@ -395,6 +396,7 @@ describe('angular', function() { expect(hashKey(dst)).toEqual(h); }); + it('should work when extending with itself', function() { var src,dst,h; dst = src = {}; @@ -405,6 +407,74 @@ describe('angular', function() { }); }); + + describe('merge', function() { + it('should recursively copy objects into dst from left to right', function() { + var dst = { foo: { bar: 'foobar' }}; + var src1 = { foo: { bazz: 'foobazz' }}; + var src2 = { foo: { bozz: 'foobozz' }}; + merge(dst, src1, src2); + expect(dst).toEqual({ + foo: { + bar: 'foobar', + bazz: 'foobazz', + bozz: 'foobozz' + } + }); + }); + + + it('should replace primitives with objects', function() { + var dst = { foo: "bloop" }; + var src = { foo: { bar: { baz: "bloop" }}}; + merge(dst, src); + expect(dst).toEqual({ + foo: { + bar: { + baz: "bloop" + } + } + }); + }); + + + it('should replace null values in destination with objects', function() { + var dst = { foo: null }; + var src = { foo: { bar: { baz: "bloop" }}}; + merge(dst, src); + expect(dst).toEqual({ + foo: { + bar: { + baz: "bloop" + } + } + }); + }); + + + it('should copy references to functions by value rather than merging', function() { + function fn() {} + var dst = { foo: 1 }; + var src = { foo: fn }; + merge(dst, src); + expect(dst).toEqual({ + foo: fn + }); + }); + + + it('should create a new array if destination property is a non-object and source property is an array', function() { + var dst = { foo: NaN }; + var src = { foo: [1,2,3] }; + merge(dst, src); + expect(dst).toEqual({ + foo: [1,2,3] + }); + expect(dst.foo).not.toBe(src.foo); + }); + }); + + describe('shallow copy', function() { it('should make a copy', function() { var original = {key:{}}; From 4949d710ae1f19ddc6e304013707c8a7af0564d7 Mon Sep 17 00:00:00 2001 From: Shahar Talmi Date: Sat, 7 Feb 2015 17:18:18 +0200 Subject: [PATCH 076/489] feat(ngModel): support conversion to timezone other than UTC Closes #11005 --- src/ng/directive/input.js | 17 +++++-- src/ng/directive/ngModel.js | 6 ++- test/ng/directive/inputSpec.js | 87 ++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 7 deletions(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index eb58f295a7eb..127ff562cb75 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -1156,8 +1156,12 @@ function createDateInputType(type, regexp, parseDate, format) { // parser/formatter in the processing chain so that the model // contains some different data format! var parsedDate = parseDate(value, previousDate); - if (timezone === 'UTC') { - parsedDate.setMinutes(parsedDate.getMinutes() - parsedDate.getTimezoneOffset()); + if (timezone) { + var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000; + if (!isNaN(requestedTimezoneOffset)) { + parsedDate = new Date(parsedDate.getTime()); + parsedDate.setMinutes(parsedDate.getMinutes() - parsedDate.getTimezoneOffset() + requestedTimezoneOffset); + } } return parsedDate; } @@ -1170,9 +1174,12 @@ function createDateInputType(type, regexp, parseDate, format) { } if (isValidDate(value)) { previousDate = value; - if (previousDate && timezone === 'UTC') { - var timezoneOffset = 60000 * previousDate.getTimezoneOffset(); - previousDate = new Date(previousDate.getTime() + timezoneOffset); + if (previousDate && timezone) { + var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000; + if (!isNaN(requestedTimezoneOffset)) { + previousDate = new Date(previousDate.getTime()); + previousDate.setMinutes(previousDate.getMinutes() + previousDate.getTimezoneOffset() - requestedTimezoneOffset); + } } return $filter('date')(value, format, timezone); } else { diff --git a/src/ng/directive/ngModel.js b/src/ng/directive/ngModel.js index 2aa897624e55..6098cd08a829 100644 --- a/src/ng/directive/ngModel.js +++ b/src/ng/directive/ngModel.js @@ -1097,8 +1097,10 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/; * - `getterSetter`: boolean value which determines whether or not to treat functions bound to `ngModel` as getters/setters. * - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for - * ``, ``, ... . Right now, the only supported value is `'UTC'`, - * otherwise the default timezone of the browser will be used. + * ``, ``, ... . It understands UTC/GMT and the + * continental US time zone abbreviations, but for general use, use a time zone offset, for + * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian) + * If not specified, the timezone of the browser will be used. * * @example diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index ad98d52abdf9..f9640cbf325f 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -613,6 +613,19 @@ describe('input', function() { }); + it('should use any timezone if specified in the options', function() { + var inputElm = helper.compileInput(''); + + helper.changeInputValueTo('2013-07'); + expect(+$rootScope.value).toBe(Date.UTC(2013, 5, 30, 19, 0, 0)); + + $rootScope.$apply(function() { + $rootScope.value = new Date(Date.UTC(2014, 5, 30, 19, 0, 0)); + }); + expect(inputElm.val()).toBe('2014-07'); + }); + + it('should label parse errors as `month`', function() { var inputElm = helper.compileInput('', { valid: false, @@ -636,6 +649,17 @@ describe('input', function() { expect(inputElm.val()).toBe('2013-12'); }); + it('should only change the month of a bound date in any timezone', function() { + var inputElm = helper.compileInput(''); + + $rootScope.$apply(function() { + $rootScope.value = new Date(Date.UTC(2013, 6, 31, 20, 0, 0)); + }); + helper.changeInputValueTo('2013-09'); + expect(+$rootScope.value).toBe(Date.UTC(2013, 7, 31, 20, 0, 0)); + expect(inputElm.val()).toBe('2013-09'); + }); + describe('min', function() { var inputElm; beforeEach(function() { @@ -814,6 +838,19 @@ describe('input', function() { }); + it('should use any timezone if specified in the options', function() { + var inputElm = helper.compileInput(''); + + helper.changeInputValueTo('2013-W03'); + expect(+$rootScope.value).toBe(Date.UTC(2013, 0, 16, 19, 0, 0)); + + $rootScope.$apply(function() { + $rootScope.value = new Date(Date.UTC(2014, 0, 16, 19, 0, 0)); + }); + expect(inputElm.val()).toBe('2014-W03'); + }); + + it('should label parse errors as `week`', function() { var inputElm = helper.compileInput('', { valid: false, @@ -990,6 +1027,30 @@ describe('input', function() { }); + it('should use any timezone if specified in the options', function() { + var inputElm = helper.compileInput(''); + + helper.changeInputValueTo('2000-01-01T06:02'); + expect(+$rootScope.value).toBe(Date.UTC(2000, 0, 1, 1, 2, 0)); + + $rootScope.$apply(function() { + $rootScope.value = new Date(Date.UTC(2001, 0, 1, 1, 2, 0)); + }); + expect(inputElm.val()).toBe('2001-01-01T06:02:00.000'); + }); + + + it('should fallback to default timezone in case an unknown timezone was passed', function() { + var inputElm = helper.compileInput( + '' + + ''); + + helper.changeGivenInputTo(inputElm.eq(0), '2000-01-01T06:02'); + helper.changeGivenInputTo(inputElm.eq(1), '2000-01-01T06:02'); + expect($rootScope.value1).toEqual($rootScope.value2); + }); + + it('should allow to specify the milliseconds', function() { var inputElm = helper.compileInput(''); @@ -1278,6 +1339,19 @@ describe('input', function() { }); + it('should use any timezone if specified in the options', function() { + var inputElm = helper.compileInput(''); + + helper.changeInputValueTo('23:02:00'); + expect(+$rootScope.value).toBe(Date.UTC(1970, 0, 1, 18, 2, 0)); + + $rootScope.$apply(function() { + $rootScope.value = new Date(Date.UTC(1971, 0, 1, 18, 2, 0)); + }); + expect(inputElm.val()).toBe('23:02:00.000'); + }); + + it('should allow to specify the milliseconds', function() { var inputElm = helper.compileInput(''); @@ -1559,6 +1633,19 @@ describe('input', function() { }); + it('should use any timezone if specified in the options', function() { + var inputElm = helper.compileInput(''); + + helper.changeInputValueTo('2000-01-01'); + expect(+$rootScope.value).toBe(Date.UTC(1999, 11, 31, 19, 0, 0)); + + $rootScope.$apply(function() { + $rootScope.value = new Date(Date.UTC(2000, 11, 31, 19, 0, 0)); + }); + expect(inputElm.val()).toBe('2001-01-01'); + }); + + it('should label parse errors as `date`', function() { var inputElm = helper.compileInput('', { valid: false, From 26ac875beb0b0eb353ef945f44d90b2c5118582b Mon Sep 17 00:00:00 2001 From: Shahar Talmi Date: Sat, 7 Feb 2015 19:35:31 +0200 Subject: [PATCH 077/489] refactor(filters/ngModel): extract common methods Closes #11005 --- src/.jshintrc | 2 ++ src/Angular.js | 22 ++++++++++++++++++++++ src/ng/directive/input.js | 12 ++---------- src/ng/filter/filters.js | 8 ++------ test/ng/filter/filtersSpec.js | 4 ++-- 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/.jshintrc b/src/.jshintrc index 897cfd9372bf..9f86b7648435 100644 --- a/src/.jshintrc +++ b/src/.jshintrc @@ -71,6 +71,8 @@ "toJsonReplacer": false, "toJson": false, "fromJson": false, + "convertTimezoneToLocal": false, + "timezoneToOffset": false, "startingTag": false, "tryDecodeURIComponent": false, "parseKeyValue": false, diff --git a/src/Angular.js b/src/Angular.js index 842b7845823a..87bce33cca96 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -66,6 +66,8 @@ toJsonReplacer: true, toJson: true, fromJson: true, + convertTimezoneToLocal: true, + timezoneToOffset: true, startingTag: true, tryDecodeURIComponent: true, parseKeyValue: true, @@ -1109,6 +1111,26 @@ function fromJson(json) { } +function timezoneToOffset(timezone, fallback) { + var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000; + return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset; +} + + +function addDateMinutes(date, minutes) { + date = new Date(date.getTime()); + date.setMinutes(date.getMinutes() + minutes); + return date; +} + + +function convertTimezoneToLocal(date, timezone, reverse) { + reverse = reverse ? -1 : 1; + var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); + return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset())); +} + + /** * @returns {string} Returns the string representation of the element. */ diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 127ff562cb75..e59ae067582d 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -1157,11 +1157,7 @@ function createDateInputType(type, regexp, parseDate, format) { // contains some different data format! var parsedDate = parseDate(value, previousDate); if (timezone) { - var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000; - if (!isNaN(requestedTimezoneOffset)) { - parsedDate = new Date(parsedDate.getTime()); - parsedDate.setMinutes(parsedDate.getMinutes() - parsedDate.getTimezoneOffset() + requestedTimezoneOffset); - } + parsedDate = convertTimezoneToLocal(parsedDate, timezone); } return parsedDate; } @@ -1175,11 +1171,7 @@ function createDateInputType(type, regexp, parseDate, format) { if (isValidDate(value)) { previousDate = value; if (previousDate && timezone) { - var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000; - if (!isNaN(requestedTimezoneOffset)) { - previousDate = new Date(previousDate.getTime()); - previousDate.setMinutes(previousDate.getMinutes() + previousDate.getTimezoneOffset() - requestedTimezoneOffset); - } + previousDate = convertTimezoneToLocal(previousDate, timezone, true); } return $filter('date')(value, format, timezone); } else { diff --git a/src/ng/filter/filters.js b/src/ng/filter/filters.js index 657d29ed7a91..314751cd4a95 100644 --- a/src/ng/filter/filters.js +++ b/src/ng/filter/filters.js @@ -488,12 +488,8 @@ function dateFilter($locale) { var dateTimezoneOffset = date.getTimezoneOffset(); if (timezone) { - var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000; - if (!isNaN(requestedTimezoneOffset)) { - date = new Date(date.getTime()); - date.setMinutes(date.getMinutes() + dateTimezoneOffset - requestedTimezoneOffset); - dateTimezoneOffset = requestedTimezoneOffset; - } + dateTimezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); + date = convertTimezoneToLocal(date, timezone, true); } forEach(parts, function(value) { fn = DATE_FORMATS[value]; diff --git a/test/ng/filter/filtersSpec.js b/test/ng/filter/filtersSpec.js index bd101b432882..0da8ff0af385 100644 --- a/test/ng/filter/filtersSpec.js +++ b/test/ng/filter/filtersSpec.js @@ -464,8 +464,8 @@ describe('filters', function() { }); it('should fallback to default timezone in case an unknown timezone was passed', function() { - var value = new angular.mock.TzDate(-2, '2003-09-10T01:02:04.000Z'); - expect(date(value, 'yyyy-MM-dd HH-mm-ssZ', 'WTF')).toEqual('2003-09-10 03-02-04+0200'); + var value = new Date(2003, 8, 10, 3, 2, 4); + expect(date(value, 'yyyy-MM-dd HH-mm-ssZ', 'WTF')).toEqual(date(value, 'yyyy-MM-dd HH-mm-ssZ')); }); }); }); From 4595850a8e5f5212a3bbebfea8e6897aa167630a Mon Sep 17 00:00:00 2001 From: Steve Mao Date: Sun, 1 Mar 2015 18:14:40 +1100 Subject: [PATCH 078/489] docs(CONTRIBUTING): add whitespaces for consistent styling Closes #11214 --- CONTRIBUTING.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f26fb9e8ddbe..8c130104a3e0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -#Contributing to AngularJS +# Contributing to AngularJS We'd love for you to contribute to our source code and to make AngularJS even better than it is today! Here are the guidelines we'd like you to follow: @@ -54,7 +54,7 @@ For large fixes, please build and test the documentation before submitting the P accidentally introduced any layout or formatting issues. You should also make sure that your commit message is labeled "docs:" and follows the **Git Commit Guidelines** outlined below. -If you're just making a small change, don't worry about filing an issue first. Use the friendly blue "Improve this doc" button at the top right of the doc page to fork the repository in-place and make a quick change on the fly. When naming the commit, it is advised to still label it according to the commit guidelines below, by starting the commit message with **docs** and referencing the filename. Since this is not obvious and some changes are made on the fly, this is not strictly necessary and we will understand if this isn't done the first few times. +If you're just making a small change, don't worry about filing an issue first. Use the friendly blue "Improve this doc" button at the top right of the doc page to fork the repository in-place and make a quick change on the fly. When naming the commit, it is advised to still label it according to the commit guidelines below, by starting the commit message with **docs** and referencing the filename. Since this is not obvious and some changes are made on the fly, this is not strictly necessary and we will understand if this isn't done the first few times. ## Submission Guidelines @@ -227,11 +227,11 @@ The subject contains succinct description of the change: * don't capitalize first letter * no dot (.) at the end -###Body +### Body Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes" The body should include the motivation for the change and contrast this with previous behavior. -###Footer +### Footer The footer should contain any information about **Breaking Changes** and is also the place to reference GitHub issues that this commit **Closes**. From 843070ee2b6ea8a2caf99b5f582d4c2368f4eda7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Sun, 25 Jan 2015 18:17:12 -0500 Subject: [PATCH 079/489] feat(ngMock): add `they` helpers for testing multiple specs There are now three new test helpers: `they`, `tthey` and `xthey`, which will create multiple `it`, `iit` and `xit` blocks, respectively, parameterized by each item in a collection that is passed. (with tests and ammendments by @petebacondarwin) Closes #10864 --- test/.jshintrc | 3 + test/helpers/privateMocks.js | 29 +++++ test/helpers/privateMocksSpec.js | 190 +++++++++++++++++++++++++++++++ test/ngMessages/messagesSpec.js | 13 --- 4 files changed, 222 insertions(+), 13 deletions(-) diff --git a/test/.jshintrc b/test/.jshintrc index 3216347a8b2b..18ef9d956730 100644 --- a/test/.jshintrc +++ b/test/.jshintrc @@ -143,6 +143,9 @@ "waitsFor": false, "runs": false, "dump": false, + "they": false, + "tthey": false, + "xthey": false, /* e2e */ "browser": false, diff --git a/test/helpers/privateMocks.js b/test/helpers/privateMocks.js index ad5b13f12989..211d3017a5ed 100644 --- a/test/helpers/privateMocks.js +++ b/test/helpers/privateMocks.js @@ -1,5 +1,34 @@ 'use strict'; +/* globals xit */ + +function baseThey(msg, vals, spec, itFn) { + var valsIsArray = isArray(vals); + + forEach(vals, function(val, key) { + var m = msg.replace('$prop', angular.toJson(valsIsArray ? val : key)); + itFn(m, function() { + /* jshint -W040 : ignore possible strict violation due to use of this */ + spec.call(this, val); + }); + }); +} + +function they(msg, vals, spec) { + baseThey(msg, vals, spec, it); +} + +function tthey(msg, vals, spec) { + baseThey(msg, vals, spec, iit); +} + +function xthey(msg, vals, spec) { + /* jshint -W040 : ignore possible strict violation due to use of this */ + baseThey(msg, vals, spec, xit); +} + + + function createMockStyleSheet(doc, wind) { doc = doc ? doc[0] : document; wind = wind || window; diff --git a/test/helpers/privateMocksSpec.js b/test/helpers/privateMocksSpec.js index dd4b19f636d4..822c40b96a59 100644 --- a/test/helpers/privateMocksSpec.js +++ b/test/helpers/privateMocksSpec.js @@ -1,6 +1,196 @@ 'use strict'; describe('private mocks', function() { + + describe('Jasmine extensions', function() { + + describe('they', function() { + it('should call `it` for each item in an array', function() { + spyOn(window, 'it'); + + they('should do stuff with $prop', ['a', 'b', 'c']); + expect(window.it.calls.length).toEqual(3); + expect(window.it).toHaveBeenCalledWith('should do stuff with "a"', jasmine.any(Function)); + expect(window.it).toHaveBeenCalledWith('should do stuff with "b"', jasmine.any(Function)); + expect(window.it).toHaveBeenCalledWith('should do stuff with "c"', jasmine.any(Function)); + }); + + + it('should pass each item in an array to the handler', function() { + var handlerSpy = jasmine.createSpy('handler'); + spyOn(window, 'it').andCallFake(function(msg, handler) { + handler(); + }); + they('should do stuff with $prop', ['a', 'b', 'c'], handlerSpy); + expect(handlerSpy).toHaveBeenCalledWith('a'); + expect(handlerSpy).toHaveBeenCalledWith('b'); + expect(handlerSpy).toHaveBeenCalledWith('c'); + }); + + + it('should call `it` for each key-value pair an object', function() { + spyOn(window, 'it'); + + they('should do stuff with $prop', {a: 1, b:2, c:3}); + expect(window.it.calls.length).toEqual(3); + expect(window.it).toHaveBeenCalledWith('should do stuff with "a"', jasmine.any(Function)); + expect(window.it).toHaveBeenCalledWith('should do stuff with "b"', jasmine.any(Function)); + expect(window.it).toHaveBeenCalledWith('should do stuff with "c"', jasmine.any(Function)); + }); + + + it('should pass each key-value pair in an object to the handler', function() { + var handlerSpy = jasmine.createSpy('handler'); + spyOn(window, 'it').andCallFake(function(msg, handler) { + handler(); + }); + they('should do stuff with $prop', {a: 1, b:2, c:3}, handlerSpy); + expect(handlerSpy).toHaveBeenCalledWith(1); + expect(handlerSpy).toHaveBeenCalledWith(2); + expect(handlerSpy).toHaveBeenCalledWith(3); + }); + + + it('should call handler with correct `this`', function() { + var handlerSpy = jasmine.createSpy('handler'); + var dummyThis = { name: 'dummyThis' }; + + spyOn(window, 'it').andCallFake(function(msg, handler) { + handler.call(dummyThis); + }); + + they('should do stuff with $prop', ['a'], handlerSpy); + expect(window.it).toHaveBeenCalledWith('should do stuff with "a"', jasmine.any(Function)); + expect(handlerSpy.mostRecentCall.object).toBe(dummyThis); + }); + }); + + + describe('tthey', function() { + it('should call `iit` for each item in an array', function() { + spyOn(window, 'iit'); + + tthey('should do stuff with $prop', ['a', 'b', 'c']); + expect(window.iit.calls.length).toEqual(3); + expect(window.iit).toHaveBeenCalledWith('should do stuff with "a"', jasmine.any(Function)); + expect(window.iit).toHaveBeenCalledWith('should do stuff with "b"', jasmine.any(Function)); + expect(window.iit).toHaveBeenCalledWith('should do stuff with "c"', jasmine.any(Function)); + }); + + + it('should pass each item in an array to the handler', function() { + var handlerSpy = jasmine.createSpy('handler'); + spyOn(window, 'iit').andCallFake(function(msg, handler) { + handler(); + }); + tthey('should do stuff with $prop', ['a', 'b', 'c'], handlerSpy); + expect(handlerSpy).toHaveBeenCalledWith('a'); + expect(handlerSpy).toHaveBeenCalledWith('b'); + expect(handlerSpy).toHaveBeenCalledWith('c'); + }); + + + it('should call `it` for each key-value pair an object', function() { + spyOn(window, 'iit'); + + tthey('should do stuff with $prop', {a: 1, b:2, c:3}); + expect(window.iit.calls.length).toEqual(3); + expect(window.iit).toHaveBeenCalledWith('should do stuff with "a"', jasmine.any(Function)); + expect(window.iit).toHaveBeenCalledWith('should do stuff with "b"', jasmine.any(Function)); + expect(window.iit).toHaveBeenCalledWith('should do stuff with "c"', jasmine.any(Function)); + }); + + + it('should pass each key-value pair in an object to the handler', function() { + var handlerSpy = jasmine.createSpy('handler'); + spyOn(window, 'iit').andCallFake(function(msg, handler) { + handler(); + }); + tthey('should do stuff with $prop', {a: 1, b:2, c:3}, handlerSpy); + expect(handlerSpy).toHaveBeenCalledWith(1); + expect(handlerSpy).toHaveBeenCalledWith(2); + expect(handlerSpy).toHaveBeenCalledWith(3); + }); + + + it('should call handler with correct `this`', function() { + var handlerSpy = jasmine.createSpy('handler'); + var dummyThis = { name: 'dummyThis' }; + + spyOn(window, 'iit').andCallFake(function(msg, handler) { + handler.call(dummyThis); + }); + + tthey('should do stuff with $prop', ['a'], handlerSpy); + expect(window.iit).toHaveBeenCalledWith('should do stuff with "a"', jasmine.any(Function)); + expect(handlerSpy.mostRecentCall.object).toBe(dummyThis); + }); + }); + + + describe('xthey', function() { + it('should call `xit` for each item in an array', function() { + spyOn(window, 'xit'); + + xthey('should do stuff with $prop', ['a', 'b', 'c']); + expect(window.xit.calls.length).toEqual(3); + expect(window.xit).toHaveBeenCalledWith('should do stuff with "a"', jasmine.any(Function)); + expect(window.xit).toHaveBeenCalledWith('should do stuff with "b"', jasmine.any(Function)); + expect(window.xit).toHaveBeenCalledWith('should do stuff with "c"', jasmine.any(Function)); + }); + + + it('should pass each item in an array to the handler', function() { + var handlerSpy = jasmine.createSpy('handler'); + spyOn(window, 'xit').andCallFake(function(msg, handler) { + handler(); + }); + xthey('should do stuff with $prop', ['a', 'b', 'c'], handlerSpy); + expect(handlerSpy).toHaveBeenCalledWith('a'); + expect(handlerSpy).toHaveBeenCalledWith('b'); + expect(handlerSpy).toHaveBeenCalledWith('c'); + }); + + + it('should call `it` for each key-value pair an object', function() { + spyOn(window, 'xit'); + + xthey('should do stuff with $prop', {a: 1, b:2, c:3}); + expect(window.xit.calls.length).toEqual(3); + expect(window.xit).toHaveBeenCalledWith('should do stuff with "a"', jasmine.any(Function)); + expect(window.xit).toHaveBeenCalledWith('should do stuff with "b"', jasmine.any(Function)); + expect(window.xit).toHaveBeenCalledWith('should do stuff with "c"', jasmine.any(Function)); + }); + + + it('should pass each key-value pair in an object to the handler', function() { + var handlerSpy = jasmine.createSpy('handler'); + spyOn(window, 'xit').andCallFake(function(msg, handler) { + handler(); + }); + xthey('should do stuff with $prop', {a: 1, b:2, c:3}, handlerSpy); + expect(handlerSpy).toHaveBeenCalledWith(1); + expect(handlerSpy).toHaveBeenCalledWith(2); + expect(handlerSpy).toHaveBeenCalledWith(3); + }); + + + it('should call handler with correct `this`', function() { + var handlerSpy = jasmine.createSpy('handler'); + var dummyThis = { name: 'dummyThis' }; + + spyOn(window, 'xit').andCallFake(function(msg, handler) { + handler.call(dummyThis); + }); + + xthey('should do stuff with $prop', ['a'], handlerSpy); + expect(window.xit).toHaveBeenCalledWith('should do stuff with "a"', jasmine.any(Function)); + expect(handlerSpy.mostRecentCall.object).toBe(dummyThis); + }); + }); + }); + + describe('createMockStyleSheet', function() { it('should allow custom styles to be created and removed when the stylesheet is destroyed', diff --git a/test/ngMessages/messagesSpec.js b/test/ngMessages/messagesSpec.js index a678b406e609..037175031ded 100644 --- a/test/ngMessages/messagesSpec.js +++ b/test/ngMessages/messagesSpec.js @@ -8,19 +8,6 @@ describe('ngMessages', function() { return (element.length ? element[0] : element).querySelectorAll('[ng-message], [ng-message-exp]'); } - function they(msg, vals, spec, focus) { - forEach(vals, function(val, key) { - var m = msg.replace('$prop', key); - (focus ? iit : it)(m, function() { - spec(val); - }); - }); - } - - function tthey(msg, vals, spec) { - they(msg, vals, spec, true); - } - function s(str) { return str.replace(/\s+/g,''); } From 33665037b1b900f3ff3eaa4d7295a88450818594 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 4 Mar 2015 12:07:51 +0000 Subject: [PATCH 080/489] style(privateMocks): remove unnecessary comment --- test/helpers/privateMocks.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/helpers/privateMocks.js b/test/helpers/privateMocks.js index 211d3017a5ed..93604bec2da4 100644 --- a/test/helpers/privateMocks.js +++ b/test/helpers/privateMocks.js @@ -23,7 +23,6 @@ function tthey(msg, vals, spec) { } function xthey(msg, vals, spec) { - /* jshint -W040 : ignore possible strict violation due to use of this */ baseThey(msg, vals, spec, xit); } From 179bc9ea0e466bb300957013a5fbf3a594b17340 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 4 Mar 2015 12:20:49 +0000 Subject: [PATCH 081/489] chore(gruntFile): add tthey and xthey to ddescribe-iit check --- Gruntfile.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 90130de79390..6f33d955b124 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -247,8 +247,19 @@ module.exports = function(grunt) { 'test/**/*.js', '!test/ngScenario/DescribeSpec.js', '!src/ng/directive/attrs.js', // legitimate xit here - '!src/ngScenario/**/*.js' - ] + '!src/ngScenario/**/*.js', + '!test/helpers/privateMocks*.js' + ], + options: { + disallowed: [ + 'iit', + 'xit', + 'tthey', + 'xthey', + 'ddescribe', + 'xdescribe' + ] + } }, "merge-conflict": { From 77ea2c8f5ffe46adf93263a2567a03fee89ae464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Wed, 4 Mar 2015 07:21:29 -0500 Subject: [PATCH 082/489] chore(privateMocks): replace multiple occurrences of $prop for they() --- test/helpers/privateMocks.js | 2 +- test/helpers/privateMocksSpec.js | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/test/helpers/privateMocks.js b/test/helpers/privateMocks.js index 93604bec2da4..8f7eb244f22e 100644 --- a/test/helpers/privateMocks.js +++ b/test/helpers/privateMocks.js @@ -6,7 +6,7 @@ function baseThey(msg, vals, spec, itFn) { var valsIsArray = isArray(vals); forEach(vals, function(val, key) { - var m = msg.replace('$prop', angular.toJson(valsIsArray ? val : key)); + var m = msg.replace(/\$prop/g, angular.toJson(valsIsArray ? val : key)); itFn(m, function() { /* jshint -W040 : ignore possible strict violation due to use of this */ spec.call(this, val); diff --git a/test/helpers/privateMocksSpec.js b/test/helpers/privateMocksSpec.js index 822c40b96a59..019dabb576c1 100644 --- a/test/helpers/privateMocksSpec.js +++ b/test/helpers/privateMocksSpec.js @@ -15,6 +15,12 @@ describe('private mocks', function() { expect(window.it).toHaveBeenCalledWith('should do stuff with "c"', jasmine.any(Function)); }); + it('should replace multiple occurrences of `$prop`', function() { + spyOn(window, 'it'); + + they('should fight $prop with $prop', ['fire']); + expect(window.it).toHaveBeenCalledWith('should fight "fire" with "fire"', jasmine.any(Function)); + }); it('should pass each item in an array to the handler', function() { var handlerSpy = jasmine.createSpy('handler'); From 067728aa7a3c7a1eb1630adb9b02e1183cb5afda Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 4 Mar 2015 13:13:34 +0000 Subject: [PATCH 083/489] chore(privateMocks): use global `angular` to access helpers in `they` When using `they` in modules such as `ngMessages` we do not have access to the internal helper functions. --- test/helpers/privateMocks.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/helpers/privateMocks.js b/test/helpers/privateMocks.js index 8f7eb244f22e..521b0c3abde5 100644 --- a/test/helpers/privateMocks.js +++ b/test/helpers/privateMocks.js @@ -3,9 +3,9 @@ /* globals xit */ function baseThey(msg, vals, spec, itFn) { - var valsIsArray = isArray(vals); + var valsIsArray = angular.isArray(vals); - forEach(vals, function(val, key) { + angular.forEach(vals, function(val, key) { var m = msg.replace(/\$prop/g, angular.toJson(valsIsArray ? val : key)); itFn(m, function() { /* jshint -W040 : ignore possible strict violation due to use of this */ From 472ea875dcc465d3d5e19ccb3fdb495bd5d365b6 Mon Sep 17 00:00:00 2001 From: gdi2290 Date: Mon, 17 Nov 2014 19:18:24 -0800 Subject: [PATCH 084/489] fix($animate): applyStyles from options on leave Closes #10068 --- src/ng/animate.js | 1 + test/ng/animateSpec.js | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ng/animate.js b/src/ng/animate.js index 752ed0e15f6f..f268773ef2af 100644 --- a/src/ng/animate.js +++ b/src/ng/animate.js @@ -210,6 +210,7 @@ var $AnimateProvider = ['$provide', function($provide) { * @return {Promise} the animation callback promise */ leave: function(element, options) { + applyStyles(element, options); element.remove(); return asyncPromise(); }, diff --git a/test/ng/animateSpec.js b/test/ng/animateSpec.js index 0c848ad1becd..ed7d17d3b98a 100644 --- a/test/ng/animateSpec.js +++ b/test/ng/animateSpec.js @@ -148,10 +148,11 @@ describe("$animate", function() { $rootScope.$digest(); assertColor('blue'); - $animate.leave(element, 'off', { - to: { color: 'blue' } + $animate.leave(element, { + to: { color: 'yellow' } }); - assertColor('blue'); //nothing should happen the element is gone anyway + $rootScope.$digest(); + assertColor('yellow'); function assertColor(color) { expect(element[0].style.color).toBe(color); From 3ca55b7be0b86b1dca5fd886a1c3a17fbf68107f Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 4 Mar 2015 21:25:01 +0000 Subject: [PATCH 085/489] docs(ngMessageExp): split ngMessage docs up to show its alias more clearly --- src/ngMessages/messages.js | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/ngMessages/messages.js b/src/ngMessages/messages.js index 53a1d2822fe9..26fe64e374f0 100644 --- a/src/ngMessages/messages.js +++ b/src/ngMessages/messages.js @@ -537,23 +537,51 @@ angular.module('ngMessages', []) * * ... * ... - * ... * * * * * ... * ... - * ... * * ``` * * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`. * * @param {expression} ngMessage|when a string value corresponding to the message key. - * @param {expression} ngMessageExp|whenExp an expression value corresponding to the message key. */ .directive('ngMessage', ngMessageDirectiveFactory('AE')) + + + /** + * @ngdoc directive + * @name ngMessageExp + * @restrict AE + * @scope + * + * @description + * `ngMessageExp` is a directive with the purpose to show and hide a particular message. + * For `ngMessageExp` to operate, a parent `ngMessages` directive on a parent DOM element + * must be situated since it determines which messages are visible based on the state + * of the provided key/value map that `ngMessages` listens on. + * + * @usage + * ```html + * + * + * ... + * + * + * + * + * ... + * + * ``` + * + * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`. + * + * @param {expression} ngMessageExp|whenExp an expression value corresponding to the message key. + */ .directive('ngMessageExp', ngMessageDirectiveFactory('A')); function ngMessageDirectiveFactory(restrict) { From 048a9d81e684e82b8f6ab719f67415fe156d0ef1 Mon Sep 17 00:00:00 2001 From: Caitlin Potter Date: Wed, 4 Mar 2015 12:14:40 -0500 Subject: [PATCH 086/489] feat(ngMock): allow mock $controller service to set up controller bindings Adds a new mock for the $controller service, in order to simplify testing using the bindToController feature. ```js var dictionaryOfControllerBindings = { data: [ { id: 0, phone: '...', name: '...' }, { id: 1, phone: '...', name: '...' }, ] }; // When the MyCtrl constructor is called, `this.data ~= dictionaryOfControllerBindings.data` $controller(MyCtrl, myLocals, dictionaryOfControllerBindings); ``` Closes #9425 Closes #11239 --- src/ngMock/angular-mocks.js | 72 ++++++++++++++++++++++++++++++++ test/ngMock/angular-mocksSpec.js | 22 ++++++++++ 2 files changed, 94 insertions(+) diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index 1b8be7d77b96..902b64142644 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -1780,6 +1780,77 @@ angular.mock.$RootElementProvider = function() { }; }; +/** + * @ngdoc service + * @name $controller + * @description + * A decorator for {@link ng.$controller} with additional `bindings` parameter, useful when testing + * controllers of directives that use {@link $compile#-bindtocontroller- `bindToController`}. + * + * + * ## Example + * + * ```js + * + * // Directive definition ... + * + * myMod.directive('myDirective', { + * controller: 'MyDirectiveController', + * bindToController: { + * name: '@' + * } + * }); + * + * + * // Controller definition ... + * + * myMod.controller('MyDirectiveController', ['log', function($log) { + * $log.info(this.name); + * })]; + * + * + * // In a test ... + * + * describe('myDirectiveController', function() { + * it('should write the bound name to the log', inject(function($controller, $log) { + * var ctrl = $controller('MyDirective', { /* no locals */ }, { name: 'Clark Kent' }); + * expect(ctrl.name).toEqual('Clark Kent'); + * expect($log.info.logs).toEqual(['Clark Kent']); + * }); + * }); + * + * ``` + * + * @param {Function|string} constructor If called with a function then it's considered to be the + * controller constructor function. Otherwise it's considered to be a string which is used + * to retrieve the controller constructor using the following steps: + * + * * check if a controller with given name is registered via `$controllerProvider` + * * check if evaluating the string on the current scope returns a constructor + * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global + * `window` object (not recommended) + * + * The string can use the `controller as property` syntax, where the controller instance is published + * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this + * to work correctly. + * + * @param {Object} locals Injection locals for Controller. + * @param {Object=} bindings Properties to add to the controller before invoking the constructor. This is used + * to simulate the `bindToController` feature and simplify certain kinds of tests. + * @return {Object} Instance of given controller. + */ +angular.mock.$ControllerDecorator = ['$delegate', function($delegate) { + return function(expression, locals, later, ident) { + if (later && typeof later === 'object') { + var create = $delegate(expression, locals, true, ident); + angular.extend(create.instance, later); + return create(); + } + return $delegate(expression, locals, later, ident); + }; +}]; + + /** * @ngdoc module * @name ngMock @@ -1808,6 +1879,7 @@ angular.module('ngMock', ['ng']).provider({ $provide.decorator('$$rAF', angular.mock.$RAFDecorator); $provide.decorator('$$asyncCallback', angular.mock.$AsyncCallbackDecorator); $provide.decorator('$rootScope', angular.mock.$RootScopeDecorator); + $provide.decorator('$controller', angular.mock.$ControllerDecorator); }]); /** diff --git a/test/ngMock/angular-mocksSpec.js b/test/ngMock/angular-mocksSpec.js index 104ece1c0aa5..7472dda3345f 100644 --- a/test/ngMock/angular-mocksSpec.js +++ b/test/ngMock/angular-mocksSpec.js @@ -1751,6 +1751,28 @@ describe('ngMock', function() { })); }); }); + + + describe('$controllerDecorator', function() { + it('should support creating controller with bindings', function() { + var called = false; + var data = [ + { name: 'derp1', id: 0 }, + { name: 'testname', id: 1 }, + { name: 'flurp', id: 2 } + ]; + module(function($controllerProvider) { + $controllerProvider.register('testCtrl', function() { + called = true; + expect(this.data).toEqual(data); + }); + }); + inject(function($controller, $rootScope) { + $controller('testCtrl', { scope: $rootScope }, { data: data }); + expect(called).toBe(true); + }); + }); + }); }); From 0bb139fbc965d89081e0aec174e417249e33330a Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 6 Mar 2015 11:26:20 +0000 Subject: [PATCH 087/489] docs(isNumber): add info about using `isFinite` to exclude `NaN` Closes #11230 --- src/Angular.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Angular.js b/src/Angular.js index 87bce33cca96..c387139f1450 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -521,6 +521,12 @@ function isString(value) {return typeof value === 'string';} * @description * Determines if a reference is a `Number`. * + * This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`. + * + * If you wish to exclude these then you can use the native + * [`isFinite'](`https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite) + * method. + * * @param {*} value Reference to check. * @returns {boolean} True if `value` is a `Number`. */ From dcf4f588f332d91fe2e1e204ffeed0f0df6fbda1 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 6 Mar 2015 11:54:55 +0000 Subject: [PATCH 088/489] docs(isNumber): fix link to isFinite --- src/Angular.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Angular.js b/src/Angular.js index c387139f1450..c365bda8ac29 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -524,7 +524,7 @@ function isString(value) {return typeof value === 'string';} * This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`. * * If you wish to exclude these then you can use the native - * [`isFinite'](`https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite) + * [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite) * method. * * @param {*} value Reference to check. From c95ef0cd37cf11905dd271b1e1dd7215fd790f82 Mon Sep 17 00:00:00 2001 From: Michel Boudreau Date: Thu, 12 Feb 2015 12:18:42 +1100 Subject: [PATCH 089/489] fix(ngJq): don't rely on jqlite Closes #11044 --- src/Angular.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/Angular.js b/src/Angular.js index c365bda8ac29..d2d5b6ace46d 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -993,18 +993,15 @@ var csp = function() { var jq = function() { if (isDefined(jq.name_)) return jq.name_; var el; - var i, ii = ngAttrPrefixes.length; + var i, ii = ngAttrPrefixes.length, prefix, name; for (i = 0; i < ii; ++i) { - if (el = document.querySelector('[' + ngAttrPrefixes[i].replace(':', '\\:') + 'jq]')) { + prefix = ngAttrPrefixes[i]; + if (el = document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) { + name = el.getAttribute(prefix + 'jq'); break; } } - var name; - if (el) { - name = getNgAttribute(el, "jq"); - } - return (jq.name_ = name); }; @@ -1265,10 +1262,9 @@ var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-']; function getNgAttribute(element, ngAttr) { var attr, i, ii = ngAttrPrefixes.length; - element = jqLite(element); for (i = 0; i < ii; ++i) { attr = ngAttrPrefixes[i] + ngAttr; - if (isString(attr = element.attr(attr))) { + if (isString(attr = element.getAttribute(attr))) { return attr; } } From e0e49ab29181f49f15232c49559f558ac010eb99 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Thu, 5 Mar 2015 19:32:16 +0100 Subject: [PATCH 090/489] chore(tests): don't rewrite urls for external scripts --- test/e2e/tools/util.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/e2e/tools/util.js b/test/e2e/tools/util.js index 313e9bda66db..0a615a7d7f84 100644 --- a/test/e2e/tools/util.js +++ b/test/e2e/tools/util.js @@ -24,6 +24,10 @@ function testExists(testname) { } function rewriteTestFile(testname, testfile) { + if (testfile.search(/^https?:\/\//) === 0) { + return testfile; + } + var i = 0; while (testfile[i] === '/') ++i; testfile = testfile.slice(i); From 86df36d2520e66b766ce840e8e33cb38fff1b7e2 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Fri, 6 Mar 2015 13:48:33 +0000 Subject: [PATCH 091/489] test(ngJq): add e2e tests Closes #11182 --- test/e2e/fixtures/ngJq/index.html | 10 ++++++++++ test/e2e/fixtures/ngJq/script.js | 4 ++++ test/e2e/fixtures/ngJqJquery/index.html | 14 ++++++++++++++ test/e2e/fixtures/ngJqJquery/script.js | 4 ++++ test/e2e/tests/ngJqSpec.js | 12 ++++++++++++ 5 files changed, 44 insertions(+) create mode 100644 test/e2e/fixtures/ngJq/index.html create mode 100644 test/e2e/fixtures/ngJq/script.js create mode 100644 test/e2e/fixtures/ngJqJquery/index.html create mode 100644 test/e2e/fixtures/ngJqJquery/script.js create mode 100644 test/e2e/tests/ngJqSpec.js diff --git a/test/e2e/fixtures/ngJq/index.html b/test/e2e/fixtures/ngJq/index.html new file mode 100644 index 000000000000..00f268c86066 --- /dev/null +++ b/test/e2e/fixtures/ngJq/index.html @@ -0,0 +1,10 @@ + + + + {{jqueryVersion}} + + + + + + diff --git a/test/e2e/fixtures/ngJq/script.js b/test/e2e/fixtures/ngJq/script.js new file mode 100644 index 000000000000..f91e1ea9cd3b --- /dev/null +++ b/test/e2e/fixtures/ngJq/script.js @@ -0,0 +1,4 @@ +angular.module('test', []) + .run(function($rootScope) { + $rootScope.jqueryVersion = window.angular.element().jquery || 'jqLite'; + }); diff --git a/test/e2e/fixtures/ngJqJquery/index.html b/test/e2e/fixtures/ngJqJquery/index.html new file mode 100644 index 000000000000..d648e16df870 --- /dev/null +++ b/test/e2e/fixtures/ngJqJquery/index.html @@ -0,0 +1,14 @@ + + + + {{jqueryVersion}} + + + + + + + + diff --git a/test/e2e/fixtures/ngJqJquery/script.js b/test/e2e/fixtures/ngJqJquery/script.js new file mode 100644 index 000000000000..f91e1ea9cd3b --- /dev/null +++ b/test/e2e/fixtures/ngJqJquery/script.js @@ -0,0 +1,4 @@ +angular.module('test', []) + .run(function($rootScope) { + $rootScope.jqueryVersion = window.angular.element().jquery || 'jqLite'; + }); diff --git a/test/e2e/tests/ngJqSpec.js b/test/e2e/tests/ngJqSpec.js new file mode 100644 index 000000000000..fd9ea368fc0d --- /dev/null +++ b/test/e2e/tests/ngJqSpec.js @@ -0,0 +1,12 @@ +describe('Customizing the jqlite / jquery version', function() { + + it('should be able to force jqlite', function() { + loadFixture("ngJq").andWaitForAngular(); + expect(element(by.binding('jqueryVersion')).getText()).toBe('jqLite'); + }); + + it('should be able to use a specific version jQuery', function() { + loadFixture("ngJqJquery").andWaitForAngular(); + expect(element(by.binding('jqueryVersion')).getText()).toBe('2.1.0'); + }); +}); From 42fb6496160f0c9bb5d6905bc70a9ee2edaa63f6 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Sun, 8 Mar 2015 13:21:32 +0100 Subject: [PATCH 092/489] docs(tutorial/0 - Bootstrapping): clarify where the callback is registered Closes #11270 --- docs/content/tutorial/step_00.ngdoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/content/tutorial/step_00.ngdoc b/docs/content/tutorial/step_00.ngdoc index c56fb3761f60..e959c4c3153b 100644 --- a/docs/content/tutorial/step_00.ngdoc +++ b/docs/content/tutorial/step_00.ngdoc @@ -65,7 +65,7 @@ __`app/index.html`:__ ## What is the code doing? -* `ng-app` directive: +**`ng-app` directive:** @@ -77,17 +77,17 @@ __`app/index.html`:__ This gives application developers the freedom to tell Angular if the entire html page or only a portion of it should be treated as the Angular application. -* AngularJS script tag: +**AngularJS script tag:** +
+ + + + + + + + + + + +
NamePhone NumberAge
{{friend.name}}{{friend.phone}}{{friend.age}}
+
+
+
+ * + * The predicate and reverse parameters can be controlled dynamically through scope properties, + * as shown in the next example. * @example From d28f2d2fd3e60547c4979c3d9163368556574022 Mon Sep 17 00:00:00 2001 From: bborowin Date: Fri, 27 Feb 2015 11:01:03 -0500 Subject: [PATCH 098/489] docs($compile): clarify when require will throw To make things less confusing, explicitly state that require WILL NOT throw a compile error if a link function is not specified. Closes #11206 stackoverflow.com/questions/28730346/require-ddo-option-of-angular-directive-does-not-throw-an-error-when-it-should --- src/ng/compile.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index 7a5869e2d407..3de0d53f0388 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -211,7 +211,8 @@ * Require another directive and inject its controller as the fourth argument to the linking function. The * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the * injected argument will be an array in corresponding order. If no such directive can be - * found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with: + * found, or if the directive does not have a controller, then an error is raised (unless no link function + * is specified, in which case error checking is skipped). The name can be prefixed with: * * * (no prefix) - Locate the required controller on the current element. Throw an error if not found. * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found. From 6f68f455e92d6f7596575978def4d487ea84cdd0 Mon Sep 17 00:00:00 2001 From: gdi2290 Date: Thu, 22 Jan 2015 10:48:14 -0800 Subject: [PATCH 099/489] feat($timeout): pass additional arguments to the callback Similar to how [`setTimeout`](mdn.io/setTimeout#Syntax) works, this commit allows users of `$timeout` to add additional parameters to the call, which will now be passed on to the callback function. Closes #10631 --- src/ng/timeout.js | 6 ++-- test/ng/timeoutSpec.js | 67 +++++++++++++++++++++++++++++++++++------- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/src/ng/timeout.js b/src/ng/timeout.js index 90555830c0b7..305739527c4c 100644 --- a/src/ng/timeout.js +++ b/src/ng/timeout.js @@ -32,6 +32,7 @@ function $TimeoutProvider() { * @param {number=} [delay=0] Delay in milliseconds. * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. + * @param {...*=} Pass additional parameters to the executed function. * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this * promise will be resolved with is the return value of the `fn` function. * @@ -43,14 +44,15 @@ function $TimeoutProvider() { fn = noop; } - var skipApply = (isDefined(invokeApply) && !invokeApply), + var args = sliceArgs(arguments, 3), + skipApply = (isDefined(invokeApply) && !invokeApply), deferred = (skipApply ? $$q : $q).defer(), promise = deferred.promise, timeoutId; timeoutId = $browser.defer(function() { try { - deferred.resolve(fn()); + deferred.resolve(fn.apply(null, args)); } catch (e) { deferred.reject(e); $exceptionHandler(e); diff --git a/test/ng/timeoutSpec.js b/test/ng/timeoutSpec.js index c3582af5a94b..2aed8b743a5f 100644 --- a/test/ng/timeoutSpec.js +++ b/test/ng/timeoutSpec.js @@ -22,7 +22,7 @@ describe('$timeout', function() { it('should call $apply after each callback is executed', inject(function($timeout, $rootScope) { var applySpy = spyOn($rootScope, '$apply').andCallThrough(); - $timeout(function() {}); + $timeout(noop); expect(applySpy).not.toHaveBeenCalled(); $timeout.flush(); @@ -30,8 +30,8 @@ describe('$timeout', function() { applySpy.reset(); - $timeout(function() {}); - $timeout(function() {}); + $timeout(noop); + $timeout(noop); $timeout.flush(); expect(applySpy.callCount).toBe(2); })); @@ -40,7 +40,7 @@ describe('$timeout', function() { it('should NOT call $apply if skipApply is set to true', inject(function($timeout, $rootScope) { var applySpy = spyOn($rootScope, '$apply').andCallThrough(); - $timeout(function() {}, 12, false); + $timeout(noop, 12, false); expect(applySpy).not.toHaveBeenCalled(); $timeout.flush(); @@ -89,8 +89,8 @@ describe('$timeout', function() { // $browser.defer.cancel is only called on cancel if the deferred object is still referenced var cancelSpy = spyOn($browser.defer, 'cancel').andCallThrough(); - var promise1 = $timeout(function() {}, 0, false); - var promise2 = $timeout(function() {}, 100, false); + var promise1 = $timeout(noop, 0, false); + var promise2 = $timeout(noop, 100, false); expect(cancelSpy).not.toHaveBeenCalled(); $timeout.flush(0); @@ -104,7 +104,6 @@ describe('$timeout', function() { expect(cancelSpy).toHaveBeenCalled(); })); - it('should allow the `fn` parameter to be optional', inject(function($timeout, log) { $timeout().then(function(value) { log('promise success: ' + value); }, log.fn('promise error')); @@ -123,6 +122,35 @@ describe('$timeout', function() { expect(log).toEqual(['promise success: undefined']); })); + it('should pass the timeout arguments in the timeout callback', + inject(function($timeout, $browser, log) { + var task1 = jasmine.createSpy('Nappa'), + task2 = jasmine.createSpy('Vegeta'); + + $timeout(task1, 9000, true, 'What does', 'the timeout', 'say about', 'its delay level'); + expect($browser.deferredFns.length).toBe(1); + + $timeout(task2, 9001, false, 'It\'s', 'over', 9000); + expect($browser.deferredFns.length).toBe(2); + + $timeout(9000, false, 'What!', 9000).then(function(value) { log('There\'s no way that can be right! ' + value); }, log.fn('It can\'t!')); + expect($browser.deferredFns.length).toBe(3); + expect(log).toEqual([]); + + $timeout.flush(0); + expect(task1).not.toHaveBeenCalled(); + + $timeout.flush(9000); + expect(task1).toHaveBeenCalledWith('What does', 'the timeout', 'say about', 'its delay level'); + + $timeout.flush(1); + expect(task2).toHaveBeenCalledWith('It\'s', 'over', 9000); + + $timeout.flush(9000); + expect(log).toEqual(['There\'s no way that can be right! undefined']); + + })); + describe('exception handling', function() { @@ -133,7 +161,7 @@ describe('$timeout', function() { it('should delegate exception to the $exceptionHandler service', inject( function($timeout, $exceptionHandler) { - $timeout(function() {throw "Test Error";}); + $timeout(function() { throw "Test Error"; }); expect($exceptionHandler.errors).toEqual([]); $timeout.flush(); @@ -145,7 +173,7 @@ describe('$timeout', function() { function($timeout, $rootScope) { var applySpy = spyOn($rootScope, '$apply').andCallThrough(); - $timeout(function() {throw "Test Error";}); + $timeout(function() { throw "Test Error"; }); expect(applySpy).not.toHaveBeenCalled(); $timeout.flush(); @@ -164,6 +192,25 @@ describe('$timeout', function() { })); + it('should pass the timeout arguments in the timeout callback even if an exception is thrown', + inject(function($timeout, log) { + var promise1 = $timeout(function(arg) { throw arg; }, 9000, true, 'Some Arguments'); + var promise2 = $timeout(function(arg1, args2) { throw arg1 + ' ' + args2; }, 9001, false, 'Are Meant', 'To Be Thrown'); + + promise1.then(log.fn('success'), function(reason) { log('error: ' + reason); }); + promise2.then(log.fn('success'), function(reason) { log('error: ' + reason); }); + + $timeout.flush(0); + expect(log).toEqual(''); + + $timeout.flush(9000); + expect(log).toEqual('error: Some Arguments'); + + $timeout.flush(1); + expect(log).toEqual('error: Some Arguments; error: Are Meant To Be Thrown'); + })); + + it('should forget references to relevant deferred even when exception is thrown', inject(function($timeout, $browser) { // $browser.defer.cancel is only called on cancel if the deferred object is still referenced @@ -242,7 +289,7 @@ describe('$timeout', function() { // $browser.defer.cancel is only called on cancel if the deferred object is still referenced var cancelSpy = spyOn($browser.defer, 'cancel').andCallThrough(); - var promise = $timeout(function() {}, 0, false); + var promise = $timeout(noop, 0, false); expect(cancelSpy).not.toHaveBeenCalled(); $timeout.cancel(promise); From 0ec083b5d1a60bcec6f7bf939528ad2602771d48 Mon Sep 17 00:00:00 2001 From: gdi2290 Date: Thu, 22 Jan 2015 10:46:00 -0800 Subject: [PATCH 100/489] feat($interval): pass additional arguments to the callback Similar to how [`setInterval`](http://mdn.io/setInterval#Syntax) works, this commit allows users of `$interval` to add additional parameters to the call, which will now be passed on to the callback function. Closes #10632 --- src/ng/interval.js | 9 +++++++-- src/ngMock/angular-mocks.js | 9 +++++++-- test/ng/intervalSpec.js | 25 +++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/ng/interval.js b/src/ng/interval.js index 1afaec797041..bd69acdef94a 100644 --- a/src/ng/interval.js +++ b/src/ng/interval.js @@ -39,6 +39,7 @@ function $IntervalProvider() { * indefinitely. * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. + * @param {...*=} Pass additional parameters to the executed function. * @returns {promise} A promise which will be notified on each iteration. * * @example @@ -132,7 +133,9 @@ function $IntervalProvider() { * */ function interval(fn, delay, count, invokeApply) { - var setInterval = $window.setInterval, + var hasParams = arguments.length > 4, + args = hasParams ? sliceArgs(arguments, 4) : [], + setInterval = $window.setInterval, clearInterval = $window.clearInterval, iteration = 0, skipApply = (isDefined(invokeApply) && !invokeApply), @@ -141,7 +144,9 @@ function $IntervalProvider() { count = isDefined(count) ? count : 0; - promise.then(null, null, fn); + promise.then(null, null, (!hasParams) ? fn : function() { + fn.apply(null, args); + }); promise.$$intervalId = setInterval(function tick() { deferred.notify(iteration++); diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index 902b64142644..fd29efaf0f07 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -425,6 +425,7 @@ angular.mock.$LogProvider = function() { * indefinitely. * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. + * @param {...*=} Pass additional parameters to the executed function. * @returns {promise} A promise which will be notified on each iteration. */ angular.mock.$IntervalProvider = function() { @@ -435,13 +436,17 @@ angular.mock.$IntervalProvider = function() { now = 0; var $interval = function(fn, delay, count, invokeApply) { - var iteration = 0, + var hasParams = arguments.length > 4, + args = hasParams ? Array.prototype.slice.call(arguments, 4) : [], + iteration = 0, skipApply = (angular.isDefined(invokeApply) && !invokeApply), deferred = (skipApply ? $$q : $q).defer(), promise = deferred.promise; count = (angular.isDefined(count)) ? count : 0; - promise.then(null, null, fn); + promise.then(null, null, (!hasParams) ? fn : function() { + fn.apply(null, args); + }); promise.$$intervalId = nextRepeatId; diff --git a/test/ng/intervalSpec.js b/test/ng/intervalSpec.js index 41cddded3307..2bc2de321a18 100644 --- a/test/ng/intervalSpec.js +++ b/test/ng/intervalSpec.js @@ -142,6 +142,31 @@ describe('$interval', function() { })); + it('should allow you to specify a number of arguments', inject(function($interval, $window) { + var task1 = jasmine.createSpy('task1'), + task2 = jasmine.createSpy('task2'), + task3 = jasmine.createSpy('task3'); + $interval(task1, 1000, 2, true, 'Task1'); + $interval(task2, 1000, 2, true, 'Task2'); + $interval(task3, 1000, 2, true, 'I', 'am', 'a', 'Task3', 'spy'); + + $window.flush(1000); + expect(task1).toHaveBeenCalledWith('Task1'); + expect(task2).toHaveBeenCalledWith('Task2'); + expect(task3).toHaveBeenCalledWith('I', 'am', 'a', 'Task3', 'spy'); + + task1.reset(); + task2.reset(); + task3.reset(); + + $window.flush(1000); + expect(task1).toHaveBeenCalledWith('Task1'); + expect(task2).toHaveBeenCalledWith('Task2'); + expect(task3).toHaveBeenCalledWith('I', 'am', 'a', 'Task3', 'spy'); + + })); + + it('should return a promise which will be updated with the count on each iteration', inject(function($interval, $window) { var log = [], From d04fab3b77e416953dfb49cbacda2a6ac1bb7788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rouven=20We=C3=9Fling?= Date: Thu, 5 Mar 2015 00:28:07 +0100 Subject: [PATCH 101/489] fix(rootScope): prevent memory leak when destroying scopes Closes #11173 Closes #11169 --- src/ng/rootScope.js | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/ng/rootScope.js b/src/ng/rootScope.js index 71a82dcda547..a75f6e28938f 100644 --- a/src/ng/rootScope.js +++ b/src/ng/rootScope.js @@ -80,9 +80,27 @@ function $RootScopeProvider() { return TTL; }; + function createChildScopeClass(parent) { + function ChildScope() { + this.$$watchers = this.$$nextSibling = + this.$$childHead = this.$$childTail = null; + this.$$listeners = {}; + this.$$listenerCount = {}; + this.$$watchersCount = 0; + this.$id = nextUid(); + this.$$ChildScope = null; + } + ChildScope.prototype = parent; + return ChildScope; + } + this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser', function($injector, $exceptionHandler, $parse, $browser) { + function destroyChildScope($event) { + $event.currentScope.$$destroyed = true; + } + /** * @ngdoc type * @name $rootScope.Scope @@ -206,16 +224,7 @@ function $RootScopeProvider() { // Only create a child scope class if somebody asks for one, // but cache it to allow the VM to optimize lookups. if (!this.$$ChildScope) { - this.$$ChildScope = function ChildScope() { - this.$$watchers = this.$$nextSibling = - this.$$childHead = this.$$childTail = null; - this.$$listeners = {}; - this.$$listenerCount = {}; - this.$$watchersCount = 0; - this.$id = nextUid(); - this.$$ChildScope = null; - }; - this.$$ChildScope.prototype = this; + this.$$ChildScope = createChildScopeClass(this); } child = new this.$$ChildScope(); } @@ -233,13 +242,9 @@ function $RootScopeProvider() { // prototypically. In all other cases, this property needs to be set // when the parent scope is destroyed. // The listener needs to be added after the parent is set - if (isolate || parent != this) child.$on('$destroy', destroyChild); + if (isolate || parent != this) child.$on('$destroy', destroyChildScope); return child; - - function destroyChild() { - child.$$destroyed = true; - } }, /** From 0cb1289c4893c8b2d68d1935c30d49a4843c403f Mon Sep 17 00:00:00 2001 From: Dave Jeffery Date: Tue, 10 Mar 2015 10:11:13 +0000 Subject: [PATCH 102/489] docs(angular.extend): remove reference to non-existent parameter The `deep` property is hard-coded to `false` and is not configurable as the docs suggest. Closes #11284 --- src/Angular.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Angular.js b/src/Angular.js index d2d5b6ace46d..efba7c07601b 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -362,8 +362,6 @@ function baseExtend(dst, objs, deep) { * * @param {Object} dst Destination object. * @param {...Object} src Source object(s). - * @param {boolean=} deep if the last parameter is set to `true`, objects are recursively merged - * (deep copy). Defaults to `false`. * @returns {Object} Reference to `dst`. */ function extend(dst) { From 45bc56e1f5fb005ee711a9099318b28403e21912 Mon Sep 17 00:00:00 2001 From: robiferentz Date: Mon, 9 Mar 2015 09:11:42 +0200 Subject: [PATCH 103/489] fix(jqLite): attr should ignore comment, text and attribute nodes Follow jQuery handling of the `attr` function Close #11038 --- src/.jshintrc | 1 + src/Angular.js | 2 ++ src/jqLite.js | 4 ++++ test/jqLiteSpec.js | 24 ++++++++++++++++++++++++ 4 files changed, 31 insertions(+) diff --git a/src/.jshintrc b/src/.jshintrc index 9f86b7648435..241e3feccb19 100644 --- a/src/.jshintrc +++ b/src/.jshintrc @@ -96,6 +96,7 @@ "skipDestroyOnNextJQueryCleanData": true, "NODE_TYPE_ELEMENT": false, + "NODE_TYPE_ATTRIBUTE": false, "NODE_TYPE_TEXT": false, "NODE_TYPE_COMMENT": false, "NODE_TYPE_COMMENT": false, diff --git a/src/Angular.js b/src/Angular.js index efba7c07601b..5dd0a4b5927d 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -88,6 +88,7 @@ createMap: true, NODE_TYPE_ELEMENT: true, + NODE_TYPE_ATTRIBUTE: true, NODE_TYPE_TEXT: true, NODE_TYPE_COMMENT: true, NODE_TYPE_DOCUMENT: true, @@ -1737,6 +1738,7 @@ function createMap() { } var NODE_TYPE_ELEMENT = 1; +var NODE_TYPE_ATTRIBUTE = 2; var NODE_TYPE_TEXT = 3; var NODE_TYPE_COMMENT = 8; var NODE_TYPE_DOCUMENT = 9; diff --git a/src/jqLite.js b/src/jqLite.js index df1ab7312ea4..5f8338e29001 100644 --- a/src/jqLite.js +++ b/src/jqLite.js @@ -587,6 +587,10 @@ forEach({ }, attr: function(element, name, value) { + var nodeType = element.nodeType; + if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) { + return; + } var lowercasedName = lowercase(name); if (BOOLEAN_ATTR[lowercasedName]) { if (isDefined(value)) { diff --git a/test/jqLiteSpec.js b/test/jqLiteSpec.js index 29848825a41a..a791641bcda0 100644 --- a/test/jqLiteSpec.js +++ b/test/jqLiteSpec.js @@ -612,6 +612,30 @@ describe('jqLite', function() { expect(elm.attr('readOnly')).toBeUndefined(); expect(elm.attr('disabled')).toBeUndefined(); }); + + it('should do nothing when setting or getting on attribute nodes', function() { + var attrNode = jqLite(document.createAttribute('myattr')); + expect(attrNode).toBeDefined(); + expect(attrNode[0].nodeType).toEqual(2); + expect(attrNode.attr('some-attribute','somevalue')).toEqual(attrNode); + expect(attrNode.attr('some-attribute')).toBeUndefined(); + }); + + it('should do nothing when setting or getting on text nodes', function() { + var textNode = jqLite(document.createTextNode('some text')); + expect(textNode).toBeDefined(); + expect(textNode[0].nodeType).toEqual(3); + expect(textNode.attr('some-attribute','somevalue')).toEqual(textNode); + expect(textNode.attr('some-attribute')).toBeUndefined(); + }); + + it('should do nothing when setting or getting on comment nodes', function() { + var comment = jqLite(document.createComment('some comment')); + expect(comment).toBeDefined(); + expect(comment[0].nodeType).toEqual(8); + expect(comment.attr('some-attribute','somevalue')).toEqual(comment); + expect(comment.attr('some-attribute')).toBeUndefined(); + }); }); From 9f72a9f525e0e7ba11f90515af69e002c61f56c2 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 6 Mar 2015 14:54:54 +0000 Subject: [PATCH 104/489] fix(ng/$locale): add ERA info in generic locale This change also updates the closure i18n converter to pull in the ERA info for generated locale files. --- i18n/src/converter.js | 2 ++ src/ng/locale.js | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/i18n/src/converter.js b/i18n/src/converter.js index 8fd6905497ef..259dbd0e747a 100644 --- a/i18n/src/converter.js +++ b/i18n/src/converter.js @@ -44,6 +44,8 @@ function convertDatetimeData(dataObj) { datetimeFormats.AMPMS = dataObj.AMPMS; datetimeFormats.FIRSTDAYOFWEEK = dataObj.FIRSTDAYOFWEEK; datetimeFormats.WEEKENDRANGE = dataObj.WEEKENDRANGE; + datetimeFormats.ERAS = dataObj.ERAS; + datetimeFormats.ERANAMES = dataObj.ERANAMES; datetimeFormats.medium = dataObj.DATEFORMATS[2] + ' ' + dataObj.TIMEFORMATS[2]; diff --git a/src/ng/locale.js b/src/ng/locale.js index fd3d5c43e9ae..e9c4dc7f72b8 100644 --- a/src/ng/locale.js +++ b/src/ng/locale.js @@ -59,7 +59,15 @@ function $LocaleProvider() { mediumDate: 'MMM d, y', shortDate: 'M/d/yy', mediumTime: 'h:mm:ss a', - shortTime: 'h:mm a' + shortTime: 'h:mm a', + ERANAMES: [ + "Before Christ", + "Anno Domini" + ], + ERAS: [ + "BC", + "AD" + ] }, pluralCat: function(num) { From 0eaf0d68ba0e64835e38fb72a1b7d3e7f92e7c1f Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 6 Mar 2015 14:54:54 +0000 Subject: [PATCH 105/489] chore(ngLocale): regenerate locale files to include ERA info --- i18n/spec/closureI18nExtractorSpec.js | 2 ++ src/ngLocale/angular-locale_aa-dj.js | 8 ++++++++ src/ngLocale/angular-locale_aa-er.js | 8 ++++++++ src/ngLocale/angular-locale_aa-et.js | 8 ++++++++ src/ngLocale/angular-locale_aa.js | 8 ++++++++ src/ngLocale/angular-locale_af-na.js | 8 ++++++++ src/ngLocale/angular-locale_af-za.js | 8 ++++++++ src/ngLocale/angular-locale_af.js | 8 ++++++++ src/ngLocale/angular-locale_agq-cm.js | 8 ++++++++ src/ngLocale/angular-locale_agq.js | 8 ++++++++ src/ngLocale/angular-locale_ak-gh.js | 8 ++++++++ src/ngLocale/angular-locale_ak.js | 8 ++++++++ src/ngLocale/angular-locale_am-et.js | 8 ++++++++ src/ngLocale/angular-locale_am.js | 8 ++++++++ src/ngLocale/angular-locale_ar-001.js | 8 ++++++++ src/ngLocale/angular-locale_ar-ae.js | 8 ++++++++ src/ngLocale/angular-locale_ar-bh.js | 8 ++++++++ src/ngLocale/angular-locale_ar-dj.js | 8 ++++++++ src/ngLocale/angular-locale_ar-dz.js | 8 ++++++++ src/ngLocale/angular-locale_ar-eg.js | 8 ++++++++ src/ngLocale/angular-locale_ar-eh.js | 8 ++++++++ src/ngLocale/angular-locale_ar-er.js | 8 ++++++++ src/ngLocale/angular-locale_ar-il.js | 8 ++++++++ src/ngLocale/angular-locale_ar-iq.js | 8 ++++++++ src/ngLocale/angular-locale_ar-jo.js | 8 ++++++++ src/ngLocale/angular-locale_ar-km.js | 8 ++++++++ src/ngLocale/angular-locale_ar-kw.js | 8 ++++++++ src/ngLocale/angular-locale_ar-lb.js | 8 ++++++++ src/ngLocale/angular-locale_ar-ly.js | 8 ++++++++ src/ngLocale/angular-locale_ar-ma.js | 8 ++++++++ src/ngLocale/angular-locale_ar-mr.js | 8 ++++++++ src/ngLocale/angular-locale_ar-om.js | 8 ++++++++ src/ngLocale/angular-locale_ar-ps.js | 8 ++++++++ src/ngLocale/angular-locale_ar-qa.js | 8 ++++++++ src/ngLocale/angular-locale_ar-sa.js | 8 ++++++++ src/ngLocale/angular-locale_ar-sd.js | 8 ++++++++ src/ngLocale/angular-locale_ar-so.js | 8 ++++++++ src/ngLocale/angular-locale_ar-ss.js | 8 ++++++++ src/ngLocale/angular-locale_ar-sy.js | 8 ++++++++ src/ngLocale/angular-locale_ar-td.js | 8 ++++++++ src/ngLocale/angular-locale_ar-tn.js | 8 ++++++++ src/ngLocale/angular-locale_ar-ye.js | 8 ++++++++ src/ngLocale/angular-locale_ar.js | 8 ++++++++ src/ngLocale/angular-locale_as-in.js | 8 ++++++++ src/ngLocale/angular-locale_as.js | 8 ++++++++ src/ngLocale/angular-locale_asa-tz.js | 8 ++++++++ src/ngLocale/angular-locale_asa.js | 8 ++++++++ src/ngLocale/angular-locale_ast-es.js | 8 ++++++++ src/ngLocale/angular-locale_ast.js | 8 ++++++++ src/ngLocale/angular-locale_az-cyrl-az.js | 8 ++++++++ src/ngLocale/angular-locale_az-cyrl.js | 8 ++++++++ src/ngLocale/angular-locale_az-latn-az.js | 8 ++++++++ src/ngLocale/angular-locale_az-latn.js | 8 ++++++++ src/ngLocale/angular-locale_az.js | 8 ++++++++ src/ngLocale/angular-locale_bas-cm.js | 8 ++++++++ src/ngLocale/angular-locale_bas.js | 8 ++++++++ src/ngLocale/angular-locale_be-by.js | 8 ++++++++ src/ngLocale/angular-locale_be.js | 8 ++++++++ src/ngLocale/angular-locale_bem-zm.js | 8 ++++++++ src/ngLocale/angular-locale_bem.js | 8 ++++++++ src/ngLocale/angular-locale_bez-tz.js | 8 ++++++++ src/ngLocale/angular-locale_bez.js | 8 ++++++++ src/ngLocale/angular-locale_bg-bg.js | 8 ++++++++ src/ngLocale/angular-locale_bg.js | 8 ++++++++ src/ngLocale/angular-locale_bm-latn-ml.js | 8 ++++++++ src/ngLocale/angular-locale_bm-latn.js | 8 ++++++++ src/ngLocale/angular-locale_bm.js | 8 ++++++++ src/ngLocale/angular-locale_bn-bd.js | 8 ++++++++ src/ngLocale/angular-locale_bn-in.js | 8 ++++++++ src/ngLocale/angular-locale_bn.js | 8 ++++++++ src/ngLocale/angular-locale_bo-cn.js | 8 ++++++++ src/ngLocale/angular-locale_bo-in.js | 8 ++++++++ src/ngLocale/angular-locale_bo.js | 8 ++++++++ src/ngLocale/angular-locale_br-fr.js | 8 ++++++++ src/ngLocale/angular-locale_br.js | 8 ++++++++ src/ngLocale/angular-locale_brx-in.js | 8 ++++++++ src/ngLocale/angular-locale_brx.js | 8 ++++++++ src/ngLocale/angular-locale_bs-cyrl-ba.js | 8 ++++++++ src/ngLocale/angular-locale_bs-cyrl.js | 8 ++++++++ src/ngLocale/angular-locale_bs-latn-ba.js | 8 ++++++++ src/ngLocale/angular-locale_bs-latn.js | 8 ++++++++ src/ngLocale/angular-locale_bs.js | 8 ++++++++ src/ngLocale/angular-locale_ca-ad.js | 8 ++++++++ src/ngLocale/angular-locale_ca-es-valencia.js | 8 ++++++++ src/ngLocale/angular-locale_ca-es.js | 8 ++++++++ src/ngLocale/angular-locale_ca-fr.js | 8 ++++++++ src/ngLocale/angular-locale_ca-it.js | 8 ++++++++ src/ngLocale/angular-locale_ca.js | 8 ++++++++ src/ngLocale/angular-locale_cgg-ug.js | 8 ++++++++ src/ngLocale/angular-locale_cgg.js | 8 ++++++++ src/ngLocale/angular-locale_chr-us.js | 8 ++++++++ src/ngLocale/angular-locale_chr.js | 8 ++++++++ src/ngLocale/angular-locale_ckb-arab-iq.js | 8 ++++++++ src/ngLocale/angular-locale_ckb-arab-ir.js | 8 ++++++++ src/ngLocale/angular-locale_ckb-arab.js | 8 ++++++++ src/ngLocale/angular-locale_ckb-iq.js | 8 ++++++++ src/ngLocale/angular-locale_ckb-ir.js | 8 ++++++++ src/ngLocale/angular-locale_ckb-latn-iq.js | 8 ++++++++ src/ngLocale/angular-locale_ckb-latn.js | 8 ++++++++ src/ngLocale/angular-locale_ckb.js | 8 ++++++++ src/ngLocale/angular-locale_cs-cz.js | 8 ++++++++ src/ngLocale/angular-locale_cs.js | 8 ++++++++ src/ngLocale/angular-locale_cy-gb.js | 8 ++++++++ src/ngLocale/angular-locale_cy.js | 8 ++++++++ src/ngLocale/angular-locale_da-dk.js | 8 ++++++++ src/ngLocale/angular-locale_da-gl.js | 8 ++++++++ src/ngLocale/angular-locale_da.js | 8 ++++++++ src/ngLocale/angular-locale_dav-ke.js | 8 ++++++++ src/ngLocale/angular-locale_dav.js | 8 ++++++++ src/ngLocale/angular-locale_de-at.js | 8 ++++++++ src/ngLocale/angular-locale_de-be.js | 8 ++++++++ src/ngLocale/angular-locale_de-ch.js | 8 ++++++++ src/ngLocale/angular-locale_de-de.js | 8 ++++++++ src/ngLocale/angular-locale_de-li.js | 8 ++++++++ src/ngLocale/angular-locale_de-lu.js | 8 ++++++++ src/ngLocale/angular-locale_de.js | 8 ++++++++ src/ngLocale/angular-locale_dje-ne.js | 8 ++++++++ src/ngLocale/angular-locale_dje.js | 8 ++++++++ src/ngLocale/angular-locale_dsb-de.js | 8 ++++++++ src/ngLocale/angular-locale_dsb.js | 8 ++++++++ src/ngLocale/angular-locale_dua-cm.js | 8 ++++++++ src/ngLocale/angular-locale_dua.js | 8 ++++++++ src/ngLocale/angular-locale_dyo-sn.js | 8 ++++++++ src/ngLocale/angular-locale_dyo.js | 8 ++++++++ src/ngLocale/angular-locale_dz-bt.js | 8 ++++++++ src/ngLocale/angular-locale_dz.js | 8 ++++++++ src/ngLocale/angular-locale_ebu-ke.js | 8 ++++++++ src/ngLocale/angular-locale_ebu.js | 8 ++++++++ src/ngLocale/angular-locale_ee-gh.js | 8 ++++++++ src/ngLocale/angular-locale_ee-tg.js | 8 ++++++++ src/ngLocale/angular-locale_ee.js | 8 ++++++++ src/ngLocale/angular-locale_el-cy.js | 8 ++++++++ src/ngLocale/angular-locale_el-gr.js | 8 ++++++++ src/ngLocale/angular-locale_el.js | 8 ++++++++ src/ngLocale/angular-locale_en-001.js | 8 ++++++++ src/ngLocale/angular-locale_en-150.js | 8 ++++++++ src/ngLocale/angular-locale_en-ag.js | 8 ++++++++ src/ngLocale/angular-locale_en-ai.js | 8 ++++++++ src/ngLocale/angular-locale_en-as.js | 8 ++++++++ src/ngLocale/angular-locale_en-au.js | 8 ++++++++ src/ngLocale/angular-locale_en-bb.js | 8 ++++++++ src/ngLocale/angular-locale_en-be.js | 8 ++++++++ src/ngLocale/angular-locale_en-bm.js | 8 ++++++++ src/ngLocale/angular-locale_en-bs.js | 8 ++++++++ src/ngLocale/angular-locale_en-bw.js | 8 ++++++++ src/ngLocale/angular-locale_en-bz.js | 8 ++++++++ src/ngLocale/angular-locale_en-ca.js | 8 ++++++++ src/ngLocale/angular-locale_en-cc.js | 8 ++++++++ src/ngLocale/angular-locale_en-ck.js | 8 ++++++++ src/ngLocale/angular-locale_en-cm.js | 8 ++++++++ src/ngLocale/angular-locale_en-cx.js | 8 ++++++++ src/ngLocale/angular-locale_en-dg.js | 8 ++++++++ src/ngLocale/angular-locale_en-dm.js | 8 ++++++++ src/ngLocale/angular-locale_en-er.js | 8 ++++++++ src/ngLocale/angular-locale_en-fj.js | 8 ++++++++ src/ngLocale/angular-locale_en-fk.js | 8 ++++++++ src/ngLocale/angular-locale_en-fm.js | 8 ++++++++ src/ngLocale/angular-locale_en-gb.js | 8 ++++++++ src/ngLocale/angular-locale_en-gd.js | 8 ++++++++ src/ngLocale/angular-locale_en-gg.js | 8 ++++++++ src/ngLocale/angular-locale_en-gh.js | 8 ++++++++ src/ngLocale/angular-locale_en-gi.js | 8 ++++++++ src/ngLocale/angular-locale_en-gm.js | 8 ++++++++ src/ngLocale/angular-locale_en-gu.js | 8 ++++++++ src/ngLocale/angular-locale_en-gy.js | 8 ++++++++ src/ngLocale/angular-locale_en-hk.js | 8 ++++++++ src/ngLocale/angular-locale_en-ie.js | 8 ++++++++ src/ngLocale/angular-locale_en-im.js | 8 ++++++++ src/ngLocale/angular-locale_en-in.js | 8 ++++++++ src/ngLocale/angular-locale_en-io.js | 8 ++++++++ src/ngLocale/angular-locale_en-iso.js | 8 ++++++++ src/ngLocale/angular-locale_en-je.js | 8 ++++++++ src/ngLocale/angular-locale_en-jm.js | 8 ++++++++ src/ngLocale/angular-locale_en-ke.js | 8 ++++++++ src/ngLocale/angular-locale_en-ki.js | 8 ++++++++ src/ngLocale/angular-locale_en-kn.js | 8 ++++++++ src/ngLocale/angular-locale_en-ky.js | 8 ++++++++ src/ngLocale/angular-locale_en-lc.js | 8 ++++++++ src/ngLocale/angular-locale_en-lr.js | 8 ++++++++ src/ngLocale/angular-locale_en-ls.js | 8 ++++++++ src/ngLocale/angular-locale_en-mg.js | 8 ++++++++ src/ngLocale/angular-locale_en-mh.js | 8 ++++++++ src/ngLocale/angular-locale_en-mo.js | 8 ++++++++ src/ngLocale/angular-locale_en-mp.js | 8 ++++++++ src/ngLocale/angular-locale_en-ms.js | 8 ++++++++ src/ngLocale/angular-locale_en-mt.js | 8 ++++++++ src/ngLocale/angular-locale_en-mu.js | 8 ++++++++ src/ngLocale/angular-locale_en-mw.js | 8 ++++++++ src/ngLocale/angular-locale_en-my.js | 8 ++++++++ src/ngLocale/angular-locale_en-na.js | 8 ++++++++ src/ngLocale/angular-locale_en-nf.js | 8 ++++++++ src/ngLocale/angular-locale_en-ng.js | 8 ++++++++ src/ngLocale/angular-locale_en-nr.js | 8 ++++++++ src/ngLocale/angular-locale_en-nu.js | 8 ++++++++ src/ngLocale/angular-locale_en-nz.js | 8 ++++++++ src/ngLocale/angular-locale_en-pg.js | 8 ++++++++ src/ngLocale/angular-locale_en-ph.js | 8 ++++++++ src/ngLocale/angular-locale_en-pk.js | 8 ++++++++ src/ngLocale/angular-locale_en-pn.js | 8 ++++++++ src/ngLocale/angular-locale_en-pr.js | 8 ++++++++ src/ngLocale/angular-locale_en-pw.js | 8 ++++++++ src/ngLocale/angular-locale_en-rw.js | 8 ++++++++ src/ngLocale/angular-locale_en-sb.js | 8 ++++++++ src/ngLocale/angular-locale_en-sc.js | 8 ++++++++ src/ngLocale/angular-locale_en-sd.js | 8 ++++++++ src/ngLocale/angular-locale_en-sg.js | 8 ++++++++ src/ngLocale/angular-locale_en-sh.js | 8 ++++++++ src/ngLocale/angular-locale_en-sl.js | 8 ++++++++ src/ngLocale/angular-locale_en-ss.js | 8 ++++++++ src/ngLocale/angular-locale_en-sx.js | 8 ++++++++ src/ngLocale/angular-locale_en-sz.js | 8 ++++++++ src/ngLocale/angular-locale_en-tc.js | 8 ++++++++ src/ngLocale/angular-locale_en-tk.js | 8 ++++++++ src/ngLocale/angular-locale_en-to.js | 8 ++++++++ src/ngLocale/angular-locale_en-tt.js | 8 ++++++++ src/ngLocale/angular-locale_en-tv.js | 8 ++++++++ src/ngLocale/angular-locale_en-tz.js | 8 ++++++++ src/ngLocale/angular-locale_en-ug.js | 8 ++++++++ src/ngLocale/angular-locale_en-um.js | 8 ++++++++ src/ngLocale/angular-locale_en-us.js | 8 ++++++++ src/ngLocale/angular-locale_en-vc.js | 8 ++++++++ src/ngLocale/angular-locale_en-vg.js | 8 ++++++++ src/ngLocale/angular-locale_en-vi.js | 8 ++++++++ src/ngLocale/angular-locale_en-vu.js | 8 ++++++++ src/ngLocale/angular-locale_en-ws.js | 8 ++++++++ src/ngLocale/angular-locale_en-za.js | 8 ++++++++ src/ngLocale/angular-locale_en-zm.js | 8 ++++++++ src/ngLocale/angular-locale_en-zw.js | 8 ++++++++ src/ngLocale/angular-locale_en.js | 8 ++++++++ src/ngLocale/angular-locale_eo-001.js | 8 ++++++++ src/ngLocale/angular-locale_eo.js | 8 ++++++++ src/ngLocale/angular-locale_es-419.js | 8 ++++++++ src/ngLocale/angular-locale_es-ar.js | 8 ++++++++ src/ngLocale/angular-locale_es-bo.js | 8 ++++++++ src/ngLocale/angular-locale_es-cl.js | 8 ++++++++ src/ngLocale/angular-locale_es-co.js | 8 ++++++++ src/ngLocale/angular-locale_es-cr.js | 8 ++++++++ src/ngLocale/angular-locale_es-cu.js | 8 ++++++++ src/ngLocale/angular-locale_es-do.js | 8 ++++++++ src/ngLocale/angular-locale_es-ea.js | 8 ++++++++ src/ngLocale/angular-locale_es-ec.js | 8 ++++++++ src/ngLocale/angular-locale_es-es.js | 8 ++++++++ src/ngLocale/angular-locale_es-gq.js | 8 ++++++++ src/ngLocale/angular-locale_es-gt.js | 8 ++++++++ src/ngLocale/angular-locale_es-hn.js | 8 ++++++++ src/ngLocale/angular-locale_es-ic.js | 8 ++++++++ src/ngLocale/angular-locale_es-mx.js | 8 ++++++++ src/ngLocale/angular-locale_es-ni.js | 8 ++++++++ src/ngLocale/angular-locale_es-pa.js | 8 ++++++++ src/ngLocale/angular-locale_es-pe.js | 8 ++++++++ src/ngLocale/angular-locale_es-ph.js | 8 ++++++++ src/ngLocale/angular-locale_es-pr.js | 8 ++++++++ src/ngLocale/angular-locale_es-py.js | 8 ++++++++ src/ngLocale/angular-locale_es-sv.js | 8 ++++++++ src/ngLocale/angular-locale_es-us.js | 8 ++++++++ src/ngLocale/angular-locale_es-uy.js | 8 ++++++++ src/ngLocale/angular-locale_es-ve.js | 8 ++++++++ src/ngLocale/angular-locale_es.js | 8 ++++++++ src/ngLocale/angular-locale_et-ee.js | 8 ++++++++ src/ngLocale/angular-locale_et.js | 8 ++++++++ src/ngLocale/angular-locale_eu-es.js | 8 ++++++++ src/ngLocale/angular-locale_eu.js | 8 ++++++++ src/ngLocale/angular-locale_ewo-cm.js | 8 ++++++++ src/ngLocale/angular-locale_ewo.js | 8 ++++++++ src/ngLocale/angular-locale_fa-af.js | 8 ++++++++ src/ngLocale/angular-locale_fa-ir.js | 8 ++++++++ src/ngLocale/angular-locale_fa.js | 8 ++++++++ src/ngLocale/angular-locale_ff-cm.js | 8 ++++++++ src/ngLocale/angular-locale_ff-gn.js | 8 ++++++++ src/ngLocale/angular-locale_ff-mr.js | 8 ++++++++ src/ngLocale/angular-locale_ff-sn.js | 8 ++++++++ src/ngLocale/angular-locale_ff.js | 8 ++++++++ src/ngLocale/angular-locale_fi-fi.js | 8 ++++++++ src/ngLocale/angular-locale_fi.js | 8 ++++++++ src/ngLocale/angular-locale_fil-ph.js | 8 ++++++++ src/ngLocale/angular-locale_fil.js | 8 ++++++++ src/ngLocale/angular-locale_fo-fo.js | 8 ++++++++ src/ngLocale/angular-locale_fo.js | 8 ++++++++ src/ngLocale/angular-locale_fr-be.js | 8 ++++++++ src/ngLocale/angular-locale_fr-bf.js | 8 ++++++++ src/ngLocale/angular-locale_fr-bi.js | 8 ++++++++ src/ngLocale/angular-locale_fr-bj.js | 8 ++++++++ src/ngLocale/angular-locale_fr-bl.js | 8 ++++++++ src/ngLocale/angular-locale_fr-ca.js | 8 ++++++++ src/ngLocale/angular-locale_fr-cd.js | 8 ++++++++ src/ngLocale/angular-locale_fr-cf.js | 8 ++++++++ src/ngLocale/angular-locale_fr-cg.js | 8 ++++++++ src/ngLocale/angular-locale_fr-ch.js | 8 ++++++++ src/ngLocale/angular-locale_fr-ci.js | 8 ++++++++ src/ngLocale/angular-locale_fr-cm.js | 8 ++++++++ src/ngLocale/angular-locale_fr-dj.js | 8 ++++++++ src/ngLocale/angular-locale_fr-dz.js | 8 ++++++++ src/ngLocale/angular-locale_fr-fr.js | 8 ++++++++ src/ngLocale/angular-locale_fr-ga.js | 8 ++++++++ src/ngLocale/angular-locale_fr-gf.js | 8 ++++++++ src/ngLocale/angular-locale_fr-gn.js | 8 ++++++++ src/ngLocale/angular-locale_fr-gp.js | 8 ++++++++ src/ngLocale/angular-locale_fr-gq.js | 8 ++++++++ src/ngLocale/angular-locale_fr-ht.js | 8 ++++++++ src/ngLocale/angular-locale_fr-km.js | 8 ++++++++ src/ngLocale/angular-locale_fr-lu.js | 8 ++++++++ src/ngLocale/angular-locale_fr-ma.js | 8 ++++++++ src/ngLocale/angular-locale_fr-mc.js | 8 ++++++++ src/ngLocale/angular-locale_fr-mf.js | 8 ++++++++ src/ngLocale/angular-locale_fr-mg.js | 8 ++++++++ src/ngLocale/angular-locale_fr-ml.js | 8 ++++++++ src/ngLocale/angular-locale_fr-mq.js | 8 ++++++++ src/ngLocale/angular-locale_fr-mr.js | 8 ++++++++ src/ngLocale/angular-locale_fr-mu.js | 8 ++++++++ src/ngLocale/angular-locale_fr-nc.js | 8 ++++++++ src/ngLocale/angular-locale_fr-ne.js | 8 ++++++++ src/ngLocale/angular-locale_fr-pf.js | 8 ++++++++ src/ngLocale/angular-locale_fr-pm.js | 8 ++++++++ src/ngLocale/angular-locale_fr-re.js | 8 ++++++++ src/ngLocale/angular-locale_fr-rw.js | 8 ++++++++ src/ngLocale/angular-locale_fr-sc.js | 8 ++++++++ src/ngLocale/angular-locale_fr-sn.js | 8 ++++++++ src/ngLocale/angular-locale_fr-sy.js | 8 ++++++++ src/ngLocale/angular-locale_fr-td.js | 8 ++++++++ src/ngLocale/angular-locale_fr-tg.js | 8 ++++++++ src/ngLocale/angular-locale_fr-tn.js | 8 ++++++++ src/ngLocale/angular-locale_fr-vu.js | 8 ++++++++ src/ngLocale/angular-locale_fr-wf.js | 8 ++++++++ src/ngLocale/angular-locale_fr-yt.js | 8 ++++++++ src/ngLocale/angular-locale_fr.js | 8 ++++++++ src/ngLocale/angular-locale_fur-it.js | 8 ++++++++ src/ngLocale/angular-locale_fur.js | 8 ++++++++ src/ngLocale/angular-locale_fy-nl.js | 8 ++++++++ src/ngLocale/angular-locale_fy.js | 8 ++++++++ src/ngLocale/angular-locale_ga-ie.js | 8 ++++++++ src/ngLocale/angular-locale_ga.js | 8 ++++++++ src/ngLocale/angular-locale_gd-gb.js | 8 ++++++++ src/ngLocale/angular-locale_gd.js | 8 ++++++++ src/ngLocale/angular-locale_gl-es.js | 8 ++++++++ src/ngLocale/angular-locale_gl.js | 8 ++++++++ src/ngLocale/angular-locale_gsw-ch.js | 8 ++++++++ src/ngLocale/angular-locale_gsw-fr.js | 8 ++++++++ src/ngLocale/angular-locale_gsw-li.js | 8 ++++++++ src/ngLocale/angular-locale_gsw.js | 8 ++++++++ src/ngLocale/angular-locale_gu-in.js | 8 ++++++++ src/ngLocale/angular-locale_gu.js | 8 ++++++++ src/ngLocale/angular-locale_guz-ke.js | 8 ++++++++ src/ngLocale/angular-locale_guz.js | 8 ++++++++ src/ngLocale/angular-locale_gv-im.js | 8 ++++++++ src/ngLocale/angular-locale_gv.js | 8 ++++++++ src/ngLocale/angular-locale_ha-latn-gh.js | 8 ++++++++ src/ngLocale/angular-locale_ha-latn-ne.js | 8 ++++++++ src/ngLocale/angular-locale_ha-latn-ng.js | 8 ++++++++ src/ngLocale/angular-locale_ha-latn.js | 8 ++++++++ src/ngLocale/angular-locale_ha.js | 8 ++++++++ src/ngLocale/angular-locale_haw-us.js | 8 ++++++++ src/ngLocale/angular-locale_haw.js | 8 ++++++++ src/ngLocale/angular-locale_he-il.js | 8 ++++++++ src/ngLocale/angular-locale_he.js | 8 ++++++++ src/ngLocale/angular-locale_hi-in.js | 8 ++++++++ src/ngLocale/angular-locale_hi.js | 8 ++++++++ src/ngLocale/angular-locale_hr-ba.js | 8 ++++++++ src/ngLocale/angular-locale_hr-hr.js | 8 ++++++++ src/ngLocale/angular-locale_hr.js | 8 ++++++++ src/ngLocale/angular-locale_hsb-de.js | 8 ++++++++ src/ngLocale/angular-locale_hsb.js | 8 ++++++++ src/ngLocale/angular-locale_hu-hu.js | 8 ++++++++ src/ngLocale/angular-locale_hu.js | 8 ++++++++ src/ngLocale/angular-locale_hy-am.js | 8 ++++++++ src/ngLocale/angular-locale_hy.js | 8 ++++++++ src/ngLocale/angular-locale_ia-fr.js | 8 ++++++++ src/ngLocale/angular-locale_ia.js | 8 ++++++++ src/ngLocale/angular-locale_id-id.js | 8 ++++++++ src/ngLocale/angular-locale_id.js | 8 ++++++++ src/ngLocale/angular-locale_ig-ng.js | 8 ++++++++ src/ngLocale/angular-locale_ig.js | 8 ++++++++ src/ngLocale/angular-locale_ii-cn.js | 8 ++++++++ src/ngLocale/angular-locale_ii.js | 8 ++++++++ src/ngLocale/angular-locale_in.js | 8 ++++++++ src/ngLocale/angular-locale_is-is.js | 8 ++++++++ src/ngLocale/angular-locale_is.js | 8 ++++++++ src/ngLocale/angular-locale_it-ch.js | 8 ++++++++ src/ngLocale/angular-locale_it-it.js | 8 ++++++++ src/ngLocale/angular-locale_it-sm.js | 8 ++++++++ src/ngLocale/angular-locale_it.js | 8 ++++++++ src/ngLocale/angular-locale_iw.js | 8 ++++++++ src/ngLocale/angular-locale_ja-jp.js | 8 ++++++++ src/ngLocale/angular-locale_ja.js | 8 ++++++++ src/ngLocale/angular-locale_jgo-cm.js | 8 ++++++++ src/ngLocale/angular-locale_jgo.js | 8 ++++++++ src/ngLocale/angular-locale_jmc-tz.js | 8 ++++++++ src/ngLocale/angular-locale_jmc.js | 8 ++++++++ src/ngLocale/angular-locale_ka-ge.js | 8 ++++++++ src/ngLocale/angular-locale_ka.js | 8 ++++++++ src/ngLocale/angular-locale_kab-dz.js | 8 ++++++++ src/ngLocale/angular-locale_kab.js | 8 ++++++++ src/ngLocale/angular-locale_kam-ke.js | 8 ++++++++ src/ngLocale/angular-locale_kam.js | 8 ++++++++ src/ngLocale/angular-locale_kde-tz.js | 8 ++++++++ src/ngLocale/angular-locale_kde.js | 8 ++++++++ src/ngLocale/angular-locale_kea-cv.js | 8 ++++++++ src/ngLocale/angular-locale_kea.js | 8 ++++++++ src/ngLocale/angular-locale_khq-ml.js | 8 ++++++++ src/ngLocale/angular-locale_khq.js | 8 ++++++++ src/ngLocale/angular-locale_ki-ke.js | 8 ++++++++ src/ngLocale/angular-locale_ki.js | 8 ++++++++ src/ngLocale/angular-locale_kk-cyrl-kz.js | 8 ++++++++ src/ngLocale/angular-locale_kk-cyrl.js | 8 ++++++++ src/ngLocale/angular-locale_kk.js | 8 ++++++++ src/ngLocale/angular-locale_kkj-cm.js | 8 ++++++++ src/ngLocale/angular-locale_kkj.js | 8 ++++++++ src/ngLocale/angular-locale_kl-gl.js | 8 ++++++++ src/ngLocale/angular-locale_kl.js | 8 ++++++++ src/ngLocale/angular-locale_kln-ke.js | 8 ++++++++ src/ngLocale/angular-locale_kln.js | 8 ++++++++ src/ngLocale/angular-locale_km-kh.js | 8 ++++++++ src/ngLocale/angular-locale_km.js | 8 ++++++++ src/ngLocale/angular-locale_kn-in.js | 8 ++++++++ src/ngLocale/angular-locale_kn.js | 8 ++++++++ src/ngLocale/angular-locale_ko-kp.js | 8 ++++++++ src/ngLocale/angular-locale_ko-kr.js | 8 ++++++++ src/ngLocale/angular-locale_ko.js | 8 ++++++++ src/ngLocale/angular-locale_kok-in.js | 8 ++++++++ src/ngLocale/angular-locale_kok.js | 8 ++++++++ src/ngLocale/angular-locale_ks-arab-in.js | 8 ++++++++ src/ngLocale/angular-locale_ks-arab.js | 8 ++++++++ src/ngLocale/angular-locale_ks.js | 8 ++++++++ src/ngLocale/angular-locale_ksb-tz.js | 8 ++++++++ src/ngLocale/angular-locale_ksb.js | 8 ++++++++ src/ngLocale/angular-locale_ksf-cm.js | 8 ++++++++ src/ngLocale/angular-locale_ksf.js | 8 ++++++++ src/ngLocale/angular-locale_ksh-de.js | 8 ++++++++ src/ngLocale/angular-locale_ksh.js | 8 ++++++++ src/ngLocale/angular-locale_kw-gb.js | 8 ++++++++ src/ngLocale/angular-locale_kw.js | 8 ++++++++ src/ngLocale/angular-locale_ky-cyrl-kg.js | 8 ++++++++ src/ngLocale/angular-locale_ky-cyrl.js | 8 ++++++++ src/ngLocale/angular-locale_ky.js | 8 ++++++++ src/ngLocale/angular-locale_lag-tz.js | 8 ++++++++ src/ngLocale/angular-locale_lag.js | 8 ++++++++ src/ngLocale/angular-locale_lb-lu.js | 8 ++++++++ src/ngLocale/angular-locale_lb.js | 8 ++++++++ src/ngLocale/angular-locale_lg-ug.js | 8 ++++++++ src/ngLocale/angular-locale_lg.js | 8 ++++++++ src/ngLocale/angular-locale_lkt-us.js | 8 ++++++++ src/ngLocale/angular-locale_lkt.js | 8 ++++++++ src/ngLocale/angular-locale_ln-ao.js | 8 ++++++++ src/ngLocale/angular-locale_ln-cd.js | 8 ++++++++ src/ngLocale/angular-locale_ln-cf.js | 8 ++++++++ src/ngLocale/angular-locale_ln-cg.js | 8 ++++++++ src/ngLocale/angular-locale_ln.js | 8 ++++++++ src/ngLocale/angular-locale_lo-la.js | 8 ++++++++ src/ngLocale/angular-locale_lo.js | 8 ++++++++ src/ngLocale/angular-locale_lt-lt.js | 8 ++++++++ src/ngLocale/angular-locale_lt.js | 8 ++++++++ src/ngLocale/angular-locale_lu-cd.js | 8 ++++++++ src/ngLocale/angular-locale_lu.js | 8 ++++++++ src/ngLocale/angular-locale_luo-ke.js | 8 ++++++++ src/ngLocale/angular-locale_luo.js | 8 ++++++++ src/ngLocale/angular-locale_luy-ke.js | 8 ++++++++ src/ngLocale/angular-locale_luy.js | 8 ++++++++ src/ngLocale/angular-locale_lv-lv.js | 8 ++++++++ src/ngLocale/angular-locale_lv.js | 8 ++++++++ src/ngLocale/angular-locale_mas-ke.js | 8 ++++++++ src/ngLocale/angular-locale_mas-tz.js | 8 ++++++++ src/ngLocale/angular-locale_mas.js | 8 ++++++++ src/ngLocale/angular-locale_mer-ke.js | 8 ++++++++ src/ngLocale/angular-locale_mer.js | 8 ++++++++ src/ngLocale/angular-locale_mfe-mu.js | 8 ++++++++ src/ngLocale/angular-locale_mfe.js | 8 ++++++++ src/ngLocale/angular-locale_mg-mg.js | 8 ++++++++ src/ngLocale/angular-locale_mg.js | 8 ++++++++ src/ngLocale/angular-locale_mgh-mz.js | 8 ++++++++ src/ngLocale/angular-locale_mgh.js | 8 ++++++++ src/ngLocale/angular-locale_mgo-cm.js | 8 ++++++++ src/ngLocale/angular-locale_mgo.js | 8 ++++++++ src/ngLocale/angular-locale_mk-mk.js | 8 ++++++++ src/ngLocale/angular-locale_mk.js | 8 ++++++++ src/ngLocale/angular-locale_ml-in.js | 8 ++++++++ src/ngLocale/angular-locale_ml.js | 8 ++++++++ src/ngLocale/angular-locale_mn-cyrl-mn.js | 8 ++++++++ src/ngLocale/angular-locale_mn-cyrl.js | 8 ++++++++ src/ngLocale/angular-locale_mn.js | 8 ++++++++ src/ngLocale/angular-locale_mr-in.js | 8 ++++++++ src/ngLocale/angular-locale_mr.js | 8 ++++++++ src/ngLocale/angular-locale_ms-latn-bn.js | 8 ++++++++ src/ngLocale/angular-locale_ms-latn-my.js | 8 ++++++++ src/ngLocale/angular-locale_ms-latn-sg.js | 8 ++++++++ src/ngLocale/angular-locale_ms-latn.js | 8 ++++++++ src/ngLocale/angular-locale_ms.js | 8 ++++++++ src/ngLocale/angular-locale_mt-mt.js | 8 ++++++++ src/ngLocale/angular-locale_mt.js | 8 ++++++++ src/ngLocale/angular-locale_mua-cm.js | 8 ++++++++ src/ngLocale/angular-locale_mua.js | 8 ++++++++ src/ngLocale/angular-locale_my-mm.js | 8 ++++++++ src/ngLocale/angular-locale_my.js | 8 ++++++++ src/ngLocale/angular-locale_naq-na.js | 8 ++++++++ src/ngLocale/angular-locale_naq.js | 8 ++++++++ src/ngLocale/angular-locale_nb-no.js | 8 ++++++++ src/ngLocale/angular-locale_nb-sj.js | 8 ++++++++ src/ngLocale/angular-locale_nb.js | 8 ++++++++ src/ngLocale/angular-locale_nd-zw.js | 8 ++++++++ src/ngLocale/angular-locale_nd.js | 8 ++++++++ src/ngLocale/angular-locale_ne-in.js | 8 ++++++++ src/ngLocale/angular-locale_ne-np.js | 8 ++++++++ src/ngLocale/angular-locale_ne.js | 8 ++++++++ src/ngLocale/angular-locale_nl-aw.js | 8 ++++++++ src/ngLocale/angular-locale_nl-be.js | 8 ++++++++ src/ngLocale/angular-locale_nl-bq.js | 8 ++++++++ src/ngLocale/angular-locale_nl-cw.js | 8 ++++++++ src/ngLocale/angular-locale_nl-nl.js | 8 ++++++++ src/ngLocale/angular-locale_nl-sr.js | 8 ++++++++ src/ngLocale/angular-locale_nl-sx.js | 8 ++++++++ src/ngLocale/angular-locale_nl.js | 8 ++++++++ src/ngLocale/angular-locale_nmg-cm.js | 8 ++++++++ src/ngLocale/angular-locale_nmg.js | 8 ++++++++ src/ngLocale/angular-locale_nn-no.js | 8 ++++++++ src/ngLocale/angular-locale_nn.js | 8 ++++++++ src/ngLocale/angular-locale_nnh-cm.js | 8 ++++++++ src/ngLocale/angular-locale_nnh.js | 8 ++++++++ src/ngLocale/angular-locale_no-no.js | 8 ++++++++ src/ngLocale/angular-locale_no.js | 8 ++++++++ src/ngLocale/angular-locale_nr-za.js | 8 ++++++++ src/ngLocale/angular-locale_nr.js | 8 ++++++++ src/ngLocale/angular-locale_nso-za.js | 8 ++++++++ src/ngLocale/angular-locale_nso.js | 8 ++++++++ src/ngLocale/angular-locale_nus-sd.js | 8 ++++++++ src/ngLocale/angular-locale_nus.js | 8 ++++++++ src/ngLocale/angular-locale_nyn-ug.js | 8 ++++++++ src/ngLocale/angular-locale_nyn.js | 8 ++++++++ src/ngLocale/angular-locale_om-et.js | 8 ++++++++ src/ngLocale/angular-locale_om-ke.js | 8 ++++++++ src/ngLocale/angular-locale_om.js | 8 ++++++++ src/ngLocale/angular-locale_or-in.js | 8 ++++++++ src/ngLocale/angular-locale_or.js | 8 ++++++++ src/ngLocale/angular-locale_os-ge.js | 8 ++++++++ src/ngLocale/angular-locale_os-ru.js | 8 ++++++++ src/ngLocale/angular-locale_os.js | 8 ++++++++ src/ngLocale/angular-locale_pa-arab-pk.js | 8 ++++++++ src/ngLocale/angular-locale_pa-arab.js | 8 ++++++++ src/ngLocale/angular-locale_pa-guru-in.js | 8 ++++++++ src/ngLocale/angular-locale_pa-guru.js | 8 ++++++++ src/ngLocale/angular-locale_pa.js | 8 ++++++++ src/ngLocale/angular-locale_pl-pl.js | 8 ++++++++ src/ngLocale/angular-locale_pl.js | 8 ++++++++ src/ngLocale/angular-locale_ps-af.js | 8 ++++++++ src/ngLocale/angular-locale_ps.js | 8 ++++++++ src/ngLocale/angular-locale_pt-ao.js | 8 ++++++++ src/ngLocale/angular-locale_pt-br.js | 8 ++++++++ src/ngLocale/angular-locale_pt-cv.js | 8 ++++++++ src/ngLocale/angular-locale_pt-gw.js | 8 ++++++++ src/ngLocale/angular-locale_pt-mo.js | 8 ++++++++ src/ngLocale/angular-locale_pt-mz.js | 8 ++++++++ src/ngLocale/angular-locale_pt-pt.js | 8 ++++++++ src/ngLocale/angular-locale_pt-st.js | 8 ++++++++ src/ngLocale/angular-locale_pt-tl.js | 8 ++++++++ src/ngLocale/angular-locale_pt.js | 8 ++++++++ src/ngLocale/angular-locale_qu-bo.js | 8 ++++++++ src/ngLocale/angular-locale_qu-ec.js | 8 ++++++++ src/ngLocale/angular-locale_qu-pe.js | 8 ++++++++ src/ngLocale/angular-locale_qu.js | 8 ++++++++ src/ngLocale/angular-locale_rm-ch.js | 8 ++++++++ src/ngLocale/angular-locale_rm.js | 8 ++++++++ src/ngLocale/angular-locale_rn-bi.js | 8 ++++++++ src/ngLocale/angular-locale_rn.js | 8 ++++++++ src/ngLocale/angular-locale_ro-md.js | 8 ++++++++ src/ngLocale/angular-locale_ro-ro.js | 8 ++++++++ src/ngLocale/angular-locale_ro.js | 8 ++++++++ src/ngLocale/angular-locale_rof-tz.js | 8 ++++++++ src/ngLocale/angular-locale_rof.js | 8 ++++++++ src/ngLocale/angular-locale_ru-by.js | 8 ++++++++ src/ngLocale/angular-locale_ru-kg.js | 8 ++++++++ src/ngLocale/angular-locale_ru-kz.js | 8 ++++++++ src/ngLocale/angular-locale_ru-md.js | 8 ++++++++ src/ngLocale/angular-locale_ru-ru.js | 8 ++++++++ src/ngLocale/angular-locale_ru-ua.js | 8 ++++++++ src/ngLocale/angular-locale_ru.js | 8 ++++++++ src/ngLocale/angular-locale_rw-rw.js | 8 ++++++++ src/ngLocale/angular-locale_rw.js | 8 ++++++++ src/ngLocale/angular-locale_rwk-tz.js | 8 ++++++++ src/ngLocale/angular-locale_rwk.js | 8 ++++++++ src/ngLocale/angular-locale_sah-ru.js | 8 ++++++++ src/ngLocale/angular-locale_sah.js | 8 ++++++++ src/ngLocale/angular-locale_saq-ke.js | 8 ++++++++ src/ngLocale/angular-locale_saq.js | 8 ++++++++ src/ngLocale/angular-locale_sbp-tz.js | 8 ++++++++ src/ngLocale/angular-locale_sbp.js | 8 ++++++++ src/ngLocale/angular-locale_se-fi.js | 8 ++++++++ src/ngLocale/angular-locale_se-no.js | 8 ++++++++ src/ngLocale/angular-locale_se-se.js | 8 ++++++++ src/ngLocale/angular-locale_se.js | 8 ++++++++ src/ngLocale/angular-locale_seh-mz.js | 8 ++++++++ src/ngLocale/angular-locale_seh.js | 8 ++++++++ src/ngLocale/angular-locale_ses-ml.js | 8 ++++++++ src/ngLocale/angular-locale_ses.js | 8 ++++++++ src/ngLocale/angular-locale_sg-cf.js | 8 ++++++++ src/ngLocale/angular-locale_sg.js | 8 ++++++++ src/ngLocale/angular-locale_shi-latn-ma.js | 8 ++++++++ src/ngLocale/angular-locale_shi-latn.js | 8 ++++++++ src/ngLocale/angular-locale_shi-tfng-ma.js | 8 ++++++++ src/ngLocale/angular-locale_shi-tfng.js | 8 ++++++++ src/ngLocale/angular-locale_shi.js | 8 ++++++++ src/ngLocale/angular-locale_si-lk.js | 8 ++++++++ src/ngLocale/angular-locale_si.js | 8 ++++++++ src/ngLocale/angular-locale_sk-sk.js | 8 ++++++++ src/ngLocale/angular-locale_sk.js | 8 ++++++++ src/ngLocale/angular-locale_sl-si.js | 8 ++++++++ src/ngLocale/angular-locale_sl.js | 8 ++++++++ src/ngLocale/angular-locale_smn-fi.js | 8 ++++++++ src/ngLocale/angular-locale_smn.js | 8 ++++++++ src/ngLocale/angular-locale_sn-zw.js | 8 ++++++++ src/ngLocale/angular-locale_sn.js | 8 ++++++++ src/ngLocale/angular-locale_so-dj.js | 8 ++++++++ src/ngLocale/angular-locale_so-et.js | 8 ++++++++ src/ngLocale/angular-locale_so-ke.js | 8 ++++++++ src/ngLocale/angular-locale_so-so.js | 8 ++++++++ src/ngLocale/angular-locale_so.js | 8 ++++++++ src/ngLocale/angular-locale_sq-al.js | 8 ++++++++ src/ngLocale/angular-locale_sq-mk.js | 8 ++++++++ src/ngLocale/angular-locale_sq-xk.js | 8 ++++++++ src/ngLocale/angular-locale_sq.js | 8 ++++++++ src/ngLocale/angular-locale_sr-cyrl-ba.js | 8 ++++++++ src/ngLocale/angular-locale_sr-cyrl-me.js | 8 ++++++++ src/ngLocale/angular-locale_sr-cyrl-rs.js | 8 ++++++++ src/ngLocale/angular-locale_sr-cyrl-xk.js | 8 ++++++++ src/ngLocale/angular-locale_sr-cyrl.js | 8 ++++++++ src/ngLocale/angular-locale_sr-latn-ba.js | 8 ++++++++ src/ngLocale/angular-locale_sr-latn-me.js | 8 ++++++++ src/ngLocale/angular-locale_sr-latn-rs.js | 8 ++++++++ src/ngLocale/angular-locale_sr-latn-xk.js | 8 ++++++++ src/ngLocale/angular-locale_sr-latn.js | 8 ++++++++ src/ngLocale/angular-locale_sr.js | 8 ++++++++ src/ngLocale/angular-locale_ss-sz.js | 8 ++++++++ src/ngLocale/angular-locale_ss-za.js | 8 ++++++++ src/ngLocale/angular-locale_ss.js | 8 ++++++++ src/ngLocale/angular-locale_ssy-er.js | 8 ++++++++ src/ngLocale/angular-locale_ssy.js | 8 ++++++++ src/ngLocale/angular-locale_sv-ax.js | 8 ++++++++ src/ngLocale/angular-locale_sv-fi.js | 8 ++++++++ src/ngLocale/angular-locale_sv-se.js | 8 ++++++++ src/ngLocale/angular-locale_sv.js | 8 ++++++++ src/ngLocale/angular-locale_sw-ke.js | 8 ++++++++ src/ngLocale/angular-locale_sw-tz.js | 8 ++++++++ src/ngLocale/angular-locale_sw-ug.js | 8 ++++++++ src/ngLocale/angular-locale_sw.js | 8 ++++++++ src/ngLocale/angular-locale_swc-cd.js | 8 ++++++++ src/ngLocale/angular-locale_swc.js | 8 ++++++++ src/ngLocale/angular-locale_ta-in.js | 8 ++++++++ src/ngLocale/angular-locale_ta-lk.js | 8 ++++++++ src/ngLocale/angular-locale_ta-my.js | 8 ++++++++ src/ngLocale/angular-locale_ta-sg.js | 8 ++++++++ src/ngLocale/angular-locale_ta.js | 8 ++++++++ src/ngLocale/angular-locale_te-in.js | 8 ++++++++ src/ngLocale/angular-locale_te.js | 8 ++++++++ src/ngLocale/angular-locale_teo-ke.js | 8 ++++++++ src/ngLocale/angular-locale_teo-ug.js | 8 ++++++++ src/ngLocale/angular-locale_teo.js | 8 ++++++++ src/ngLocale/angular-locale_th-th.js | 8 ++++++++ src/ngLocale/angular-locale_th.js | 8 ++++++++ src/ngLocale/angular-locale_ti-er.js | 8 ++++++++ src/ngLocale/angular-locale_ti-et.js | 8 ++++++++ src/ngLocale/angular-locale_ti.js | 8 ++++++++ src/ngLocale/angular-locale_tl.js | 8 ++++++++ src/ngLocale/angular-locale_tn-bw.js | 8 ++++++++ src/ngLocale/angular-locale_tn-za.js | 8 ++++++++ src/ngLocale/angular-locale_tn.js | 8 ++++++++ src/ngLocale/angular-locale_to-to.js | 8 ++++++++ src/ngLocale/angular-locale_to.js | 8 ++++++++ src/ngLocale/angular-locale_tr-cy.js | 8 ++++++++ src/ngLocale/angular-locale_tr-tr.js | 8 ++++++++ src/ngLocale/angular-locale_tr.js | 8 ++++++++ src/ngLocale/angular-locale_ts-za.js | 8 ++++++++ src/ngLocale/angular-locale_ts.js | 8 ++++++++ src/ngLocale/angular-locale_twq-ne.js | 8 ++++++++ src/ngLocale/angular-locale_twq.js | 8 ++++++++ src/ngLocale/angular-locale_tzm-latn-ma.js | 8 ++++++++ src/ngLocale/angular-locale_tzm-latn.js | 8 ++++++++ src/ngLocale/angular-locale_tzm.js | 8 ++++++++ src/ngLocale/angular-locale_ug-arab-cn.js | 8 ++++++++ src/ngLocale/angular-locale_ug-arab.js | 8 ++++++++ src/ngLocale/angular-locale_ug.js | 8 ++++++++ src/ngLocale/angular-locale_uk-ua.js | 8 ++++++++ src/ngLocale/angular-locale_uk.js | 8 ++++++++ src/ngLocale/angular-locale_ur-in.js | 8 ++++++++ src/ngLocale/angular-locale_ur-pk.js | 8 ++++++++ src/ngLocale/angular-locale_ur.js | 8 ++++++++ src/ngLocale/angular-locale_uz-arab-af.js | 8 ++++++++ src/ngLocale/angular-locale_uz-arab.js | 8 ++++++++ src/ngLocale/angular-locale_uz-cyrl-uz.js | 8 ++++++++ src/ngLocale/angular-locale_uz-cyrl.js | 8 ++++++++ src/ngLocale/angular-locale_uz-latn-uz.js | 8 ++++++++ src/ngLocale/angular-locale_uz-latn.js | 8 ++++++++ src/ngLocale/angular-locale_uz.js | 8 ++++++++ src/ngLocale/angular-locale_vai-latn-lr.js | 8 ++++++++ src/ngLocale/angular-locale_vai-latn.js | 8 ++++++++ src/ngLocale/angular-locale_vai-vaii-lr.js | 8 ++++++++ src/ngLocale/angular-locale_vai-vaii.js | 8 ++++++++ src/ngLocale/angular-locale_vai.js | 8 ++++++++ src/ngLocale/angular-locale_ve-za.js | 8 ++++++++ src/ngLocale/angular-locale_ve.js | 8 ++++++++ src/ngLocale/angular-locale_vi-vn.js | 8 ++++++++ src/ngLocale/angular-locale_vi.js | 8 ++++++++ src/ngLocale/angular-locale_vo-001.js | 8 ++++++++ src/ngLocale/angular-locale_vo.js | 8 ++++++++ src/ngLocale/angular-locale_vun-tz.js | 8 ++++++++ src/ngLocale/angular-locale_vun.js | 8 ++++++++ src/ngLocale/angular-locale_wae-ch.js | 8 ++++++++ src/ngLocale/angular-locale_wae.js | 8 ++++++++ src/ngLocale/angular-locale_xog-ug.js | 8 ++++++++ src/ngLocale/angular-locale_xog.js | 8 ++++++++ src/ngLocale/angular-locale_yav-cm.js | 8 ++++++++ src/ngLocale/angular-locale_yav.js | 8 ++++++++ src/ngLocale/angular-locale_yi-001.js | 8 ++++++++ src/ngLocale/angular-locale_yi.js | 8 ++++++++ src/ngLocale/angular-locale_yo-bj.js | 8 ++++++++ src/ngLocale/angular-locale_yo-ng.js | 8 ++++++++ src/ngLocale/angular-locale_yo.js | 8 ++++++++ src/ngLocale/angular-locale_zgh-ma.js | 8 ++++++++ src/ngLocale/angular-locale_zgh.js | 8 ++++++++ src/ngLocale/angular-locale_zh-cn.js | 8 ++++++++ src/ngLocale/angular-locale_zh-hans-cn.js | 8 ++++++++ src/ngLocale/angular-locale_zh-hans-hk.js | 8 ++++++++ src/ngLocale/angular-locale_zh-hans-mo.js | 8 ++++++++ src/ngLocale/angular-locale_zh-hans-sg.js | 8 ++++++++ src/ngLocale/angular-locale_zh-hans.js | 8 ++++++++ src/ngLocale/angular-locale_zh-hant-hk.js | 8 ++++++++ src/ngLocale/angular-locale_zh-hant-mo.js | 8 ++++++++ src/ngLocale/angular-locale_zh-hant-tw.js | 8 ++++++++ src/ngLocale/angular-locale_zh-hant.js | 8 ++++++++ src/ngLocale/angular-locale_zh-hk.js | 8 ++++++++ src/ngLocale/angular-locale_zh-tw.js | 8 ++++++++ src/ngLocale/angular-locale_zh.js | 8 ++++++++ src/ngLocale/angular-locale_zu-za.js | 8 ++++++++ src/ngLocale/angular-locale_zu.js | 8 ++++++++ 729 files changed, 5826 insertions(+) diff --git a/i18n/spec/closureI18nExtractorSpec.js b/i18n/spec/closureI18nExtractorSpec.js index a5487469b5f9..07641ca9ffce 100644 --- a/i18n/spec/closureI18nExtractorSpec.js +++ b/i18n/spec/closureI18nExtractorSpec.js @@ -187,6 +187,8 @@ describe("extractDateTimeSymbols", function() { FIRSTDAYOFWEEK: 6, WEEKENDRANGE: [5, 6], AMPMS: ['AM', 'PM'], + ERAS: ['av. J.-C.', 'ap. J.-C.'], + ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'], medium: 'yyyy-MM-dd HH:mm:ss', short: 'yy-MM-dd HH:mm', fullDate: 'EEEE d MMMM y', diff --git a/src/ngLocale/angular-locale_aa-dj.js b/src/ngLocale/angular-locale_aa-dj.js index cea757558c43..2fe0c3034d79 100644 --- a/src/ngLocale/angular-locale_aa-dj.js +++ b/src/ngLocale/angular-locale_aa-dj.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Gumqata", "Sabti" ], + "ERANAMES": [ + "Yaasuusuk Duma", + "Yaasuusuk Wadir" + ], + "ERAS": [ + "Yaasuusuk Duma", + "Yaasuusuk Wadir" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "Qunxa Garablu", diff --git a/src/ngLocale/angular-locale_aa-er.js b/src/ngLocale/angular-locale_aa-er.js index 2e4a22b3721b..48c1e7c3999e 100644 --- a/src/ngLocale/angular-locale_aa-er.js +++ b/src/ngLocale/angular-locale_aa-er.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Gumqata", "Sabti" ], + "ERANAMES": [ + "Yaasuusuk Duma", + "Yaasuusuk Wadir" + ], + "ERAS": [ + "Yaasuusuk Duma", + "Yaasuusuk Wadir" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Qunxa Garablu", diff --git a/src/ngLocale/angular-locale_aa-et.js b/src/ngLocale/angular-locale_aa-et.js index af3ae76ed771..03b62551e93a 100644 --- a/src/ngLocale/angular-locale_aa-et.js +++ b/src/ngLocale/angular-locale_aa-et.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Gumqata", "Sabti" ], + "ERANAMES": [ + "Yaasuusuk Duma", + "Yaasuusuk Wadir" + ], + "ERAS": [ + "Yaasuusuk Duma", + "Yaasuusuk Wadir" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Qunxa Garablu", diff --git a/src/ngLocale/angular-locale_aa.js b/src/ngLocale/angular-locale_aa.js index 06bbf1250e52..661fa2e1dfe1 100644 --- a/src/ngLocale/angular-locale_aa.js +++ b/src/ngLocale/angular-locale_aa.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Gumqata", "Sabti" ], + "ERANAMES": [ + "Yaasuusuk Duma", + "Yaasuusuk Wadir" + ], + "ERAS": [ + "Yaasuusuk Duma", + "Yaasuusuk Wadir" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Qunxa Garablu", diff --git a/src/ngLocale/angular-locale_af-na.js b/src/ngLocale/angular-locale_af-na.js index 8dea60e9bf1a..a8d13be87f6b 100644 --- a/src/ngLocale/angular-locale_af-na.js +++ b/src/ngLocale/angular-locale_af-na.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Vrydag", "Saterdag" ], + "ERANAMES": [ + "voor Christus", + "na Christus" + ], + "ERAS": [ + "v.C.", + "n.C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januarie", diff --git a/src/ngLocale/angular-locale_af-za.js b/src/ngLocale/angular-locale_af-za.js index 47f2bea6b02c..0ef24da8935a 100644 --- a/src/ngLocale/angular-locale_af-za.js +++ b/src/ngLocale/angular-locale_af-za.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Vrydag", "Saterdag" ], + "ERANAMES": [ + "voor Christus", + "na Christus" + ], + "ERAS": [ + "v.C.", + "n.C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Januarie", diff --git a/src/ngLocale/angular-locale_af.js b/src/ngLocale/angular-locale_af.js index 6b54357c5011..07ba6aab0508 100644 --- a/src/ngLocale/angular-locale_af.js +++ b/src/ngLocale/angular-locale_af.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Vrydag", "Saterdag" ], + "ERANAMES": [ + "voor Christus", + "na Christus" + ], + "ERAS": [ + "v.C.", + "n.C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Januarie", diff --git a/src/ngLocale/angular-locale_agq-cm.js b/src/ngLocale/angular-locale_agq-cm.js index cee88db7d0e8..9d3f9e9cdd81 100644 --- a/src/ngLocale/angular-locale_agq-cm.js +++ b/src/ngLocale/angular-locale_agq-cm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "tsu\u0294ugh\u0268\u0302m", "tsu\u0294ndz\u0268k\u0254\u0294\u0254" ], + "ERANAMES": [ + "S\u011be K\u0268\u0300lesto", + "B\u01cea K\u0268\u0300lesto" + ], + "ERAS": [ + "SK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "ndz\u0254\u0300\u014b\u0254\u0300n\u00f9m", diff --git a/src/ngLocale/angular-locale_agq.js b/src/ngLocale/angular-locale_agq.js index cca741bc55a6..2bd28260de13 100644 --- a/src/ngLocale/angular-locale_agq.js +++ b/src/ngLocale/angular-locale_agq.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "tsu\u0294ugh\u0268\u0302m", "tsu\u0294ndz\u0268k\u0254\u0294\u0254" ], + "ERANAMES": [ + "S\u011be K\u0268\u0300lesto", + "B\u01cea K\u0268\u0300lesto" + ], + "ERAS": [ + "SK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "ndz\u0254\u0300\u014b\u0254\u0300n\u00f9m", diff --git a/src/ngLocale/angular-locale_ak-gh.js b/src/ngLocale/angular-locale_ak-gh.js index 4f39e2d0bebc..94919d6ff55d 100644 --- a/src/ngLocale/angular-locale_ak-gh.js +++ b/src/ngLocale/angular-locale_ak-gh.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Fida", "Memeneda" ], + "ERANAMES": [ + "Ansa Kristo", + "Kristo Ekyiri" + ], + "ERAS": [ + "AK", + "KE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Sanda-\u0186p\u025bp\u0254n", diff --git a/src/ngLocale/angular-locale_ak.js b/src/ngLocale/angular-locale_ak.js index 7db5f5ebfadf..84b1d96ca83b 100644 --- a/src/ngLocale/angular-locale_ak.js +++ b/src/ngLocale/angular-locale_ak.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Fida", "Memeneda" ], + "ERANAMES": [ + "Ansa Kristo", + "Kristo Ekyiri" + ], + "ERAS": [ + "AK", + "KE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Sanda-\u0186p\u025bp\u0254n", diff --git a/src/ngLocale/angular-locale_am-et.js b/src/ngLocale/angular-locale_am-et.js index 84f4209ed4d3..c3f015ff1bdb 100644 --- a/src/ngLocale/angular-locale_am-et.js +++ b/src/ngLocale/angular-locale_am-et.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u12d3\u122d\u1265", "\u1245\u12f3\u121c" ], + "ERANAMES": [ + "\u12d3\u1218\u1270 \u12d3\u1208\u121d", + "\u12d3\u1218\u1270 \u121d\u1215\u1228\u1275" + ], + "ERAS": [ + "\u12d3/\u12d3", + "\u12d3/\u121d" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u1303\u1295\u12e9\u12c8\u122a", diff --git a/src/ngLocale/angular-locale_am.js b/src/ngLocale/angular-locale_am.js index f93252c4ca68..3de07d74c895 100644 --- a/src/ngLocale/angular-locale_am.js +++ b/src/ngLocale/angular-locale_am.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u12d3\u122d\u1265", "\u1245\u12f3\u121c" ], + "ERANAMES": [ + "\u12d3\u1218\u1270 \u12d3\u1208\u121d", + "\u12d3\u1218\u1270 \u121d\u1215\u1228\u1275" + ], + "ERAS": [ + "\u12d3/\u12d3", + "\u12d3/\u121d" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u1303\u1295\u12e9\u12c8\u122a", diff --git a/src/ngLocale/angular-locale_ar-001.js b/src/ngLocale/angular-locale_ar-001.js index 7dd78603c976..52a1c6971f0e 100644 --- a/src/ngLocale/angular-locale_ar-001.js +++ b/src/ngLocale/angular-locale_ar-001.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-ae.js b/src/ngLocale/angular-locale_ar-ae.js index 67bd6a078b13..ee310fbf5be5 100644 --- a/src/ngLocale/angular-locale_ar-ae.js +++ b/src/ngLocale/angular-locale_ar-ae.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-bh.js b/src/ngLocale/angular-locale_ar-bh.js index b8c37379046d..5e38ba7671f2 100644 --- a/src/ngLocale/angular-locale_ar-bh.js +++ b/src/ngLocale/angular-locale_ar-bh.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-dj.js b/src/ngLocale/angular-locale_ar-dj.js index 30fde36f54fa..941bad72ffb4 100644 --- a/src/ngLocale/angular-locale_ar-dj.js +++ b/src/ngLocale/angular-locale_ar-dj.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-dz.js b/src/ngLocale/angular-locale_ar-dz.js index 5a514b889290..9d6927c06292 100644 --- a/src/ngLocale/angular-locale_ar-dz.js +++ b/src/ngLocale/angular-locale_ar-dz.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u062c\u0627\u0646\u0641\u064a", diff --git a/src/ngLocale/angular-locale_ar-eg.js b/src/ngLocale/angular-locale_ar-eg.js index bfa9d2611e84..951f79d36882 100644 --- a/src/ngLocale/angular-locale_ar-eg.js +++ b/src/ngLocale/angular-locale_ar-eg.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-eh.js b/src/ngLocale/angular-locale_ar-eh.js index 530d5c2e0dde..4a2618949f58 100644 --- a/src/ngLocale/angular-locale_ar-eh.js +++ b/src/ngLocale/angular-locale_ar-eh.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-er.js b/src/ngLocale/angular-locale_ar-er.js index c359f3943b2e..d7f1fe97aa8a 100644 --- a/src/ngLocale/angular-locale_ar-er.js +++ b/src/ngLocale/angular-locale_ar-er.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-il.js b/src/ngLocale/angular-locale_ar-il.js index f7a621fa1357..4e540bb0896b 100644 --- a/src/ngLocale/angular-locale_ar-il.js +++ b/src/ngLocale/angular-locale_ar-il.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-iq.js b/src/ngLocale/angular-locale_ar-iq.js index 3e10b61b26cc..b17dc1e2ce4c 100644 --- a/src/ngLocale/angular-locale_ar-iq.js +++ b/src/ngLocale/angular-locale_ar-iq.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a", diff --git a/src/ngLocale/angular-locale_ar-jo.js b/src/ngLocale/angular-locale_ar-jo.js index 01d103def47d..a12d7a63da3d 100644 --- a/src/ngLocale/angular-locale_ar-jo.js +++ b/src/ngLocale/angular-locale_ar-jo.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a", diff --git a/src/ngLocale/angular-locale_ar-km.js b/src/ngLocale/angular-locale_ar-km.js index 1f5a18c76800..10adb31f053c 100644 --- a/src/ngLocale/angular-locale_ar-km.js +++ b/src/ngLocale/angular-locale_ar-km.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-kw.js b/src/ngLocale/angular-locale_ar-kw.js index 1074017470b8..2adce3df90d6 100644 --- a/src/ngLocale/angular-locale_ar-kw.js +++ b/src/ngLocale/angular-locale_ar-kw.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-lb.js b/src/ngLocale/angular-locale_ar-lb.js index 58885170bbb0..dc4aca6adff7 100644 --- a/src/ngLocale/angular-locale_ar-lb.js +++ b/src/ngLocale/angular-locale_ar-lb.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a", diff --git a/src/ngLocale/angular-locale_ar-ly.js b/src/ngLocale/angular-locale_ar-ly.js index 8c18ade5e3bb..dd7f999f54f7 100644 --- a/src/ngLocale/angular-locale_ar-ly.js +++ b/src/ngLocale/angular-locale_ar-ly.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-ma.js b/src/ngLocale/angular-locale_ar-ma.js index 1f9ba046235a..c7fb49e0cb0a 100644 --- a/src/ngLocale/angular-locale_ar-ma.js +++ b/src/ngLocale/angular-locale_ar-ma.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-mr.js b/src/ngLocale/angular-locale_ar-mr.js index 95ddc3fe8d2a..c01691cc0980 100644 --- a/src/ngLocale/angular-locale_ar-mr.js +++ b/src/ngLocale/angular-locale_ar-mr.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-om.js b/src/ngLocale/angular-locale_ar-om.js index 3a2739a25feb..f072d769228c 100644 --- a/src/ngLocale/angular-locale_ar-om.js +++ b/src/ngLocale/angular-locale_ar-om.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-ps.js b/src/ngLocale/angular-locale_ar-ps.js index 0ed68b456d7c..1d05406612e1 100644 --- a/src/ngLocale/angular-locale_ar-ps.js +++ b/src/ngLocale/angular-locale_ar-ps.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a", diff --git a/src/ngLocale/angular-locale_ar-qa.js b/src/ngLocale/angular-locale_ar-qa.js index a1c3503807c3..e3c83e32131c 100644 --- a/src/ngLocale/angular-locale_ar-qa.js +++ b/src/ngLocale/angular-locale_ar-qa.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-sa.js b/src/ngLocale/angular-locale_ar-sa.js index 09d5e4b81d4c..83adcf9586ec 100644 --- a/src/ngLocale/angular-locale_ar-sa.js +++ b/src/ngLocale/angular-locale_ar-sa.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-sd.js b/src/ngLocale/angular-locale_ar-sd.js index 57b9fc09e8d6..b5ac27e74ba1 100644 --- a/src/ngLocale/angular-locale_ar-sd.js +++ b/src/ngLocale/angular-locale_ar-sd.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-so.js b/src/ngLocale/angular-locale_ar-so.js index 802e7c649963..ebaded222309 100644 --- a/src/ngLocale/angular-locale_ar-so.js +++ b/src/ngLocale/angular-locale_ar-so.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-ss.js b/src/ngLocale/angular-locale_ar-ss.js index edc45a10de16..b5fe6f653e19 100644 --- a/src/ngLocale/angular-locale_ar-ss.js +++ b/src/ngLocale/angular-locale_ar-ss.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-sy.js b/src/ngLocale/angular-locale_ar-sy.js index 943dfc97cbb6..87b93dcf3739 100644 --- a/src/ngLocale/angular-locale_ar-sy.js +++ b/src/ngLocale/angular-locale_ar-sy.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a", diff --git a/src/ngLocale/angular-locale_ar-td.js b/src/ngLocale/angular-locale_ar-td.js index 54e993a9da94..3de8670838e6 100644 --- a/src/ngLocale/angular-locale_ar-td.js +++ b/src/ngLocale/angular-locale_ar-td.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar-tn.js b/src/ngLocale/angular-locale_ar-tn.js index 73f631193710..5234adddc8ff 100644 --- a/src/ngLocale/angular-locale_ar-tn.js +++ b/src/ngLocale/angular-locale_ar-tn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u062c\u0627\u0646\u0641\u064a", diff --git a/src/ngLocale/angular-locale_ar-ye.js b/src/ngLocale/angular-locale_ar-ye.js index b45c813b8272..40f7310cc151 100644 --- a/src/ngLocale/angular-locale_ar-ye.js +++ b/src/ngLocale/angular-locale_ar-ye.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_ar.js b/src/ngLocale/angular-locale_ar.js index 749b48a77367..37fc21359efb 100644 --- a/src/ngLocale/angular-locale_ar.js +++ b/src/ngLocale/angular-locale_ar.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0627\u0644\u062c\u0645\u0639\u0629", "\u0627\u0644\u0633\u0628\u062a" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f", + "\u0645\u064a\u0644\u0627\u062f\u064a" + ], + "ERAS": [ + "\u0642.\u0645", + "\u0645" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u064a\u0646\u0627\u064a\u0631", diff --git a/src/ngLocale/angular-locale_as-in.js b/src/ngLocale/angular-locale_as-in.js index 7e3a110fd9d9..d98789d9d979 100644 --- a/src/ngLocale/angular-locale_as-in.js +++ b/src/ngLocale/angular-locale_as-in.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u09b6\u09c1\u0995\u09cd\u09f0\u09ac\u09be\u09f0", "\u09b6\u09a8\u09bf\u09ac\u09be\u09f0" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u099c\u09be\u09a8\u09c1\u09f1\u09be\u09f0\u09c0", diff --git a/src/ngLocale/angular-locale_as.js b/src/ngLocale/angular-locale_as.js index b9b75e5eec0e..db6a4e4677ad 100644 --- a/src/ngLocale/angular-locale_as.js +++ b/src/ngLocale/angular-locale_as.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u09b6\u09c1\u0995\u09cd\u09f0\u09ac\u09be\u09f0", "\u09b6\u09a8\u09bf\u09ac\u09be\u09f0" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u099c\u09be\u09a8\u09c1\u09f1\u09be\u09f0\u09c0", diff --git a/src/ngLocale/angular-locale_asa-tz.js b/src/ngLocale/angular-locale_asa-tz.js index a2a3e6bf8f11..5add04ffb679 100644 --- a/src/ngLocale/angular-locale_asa-tz.js +++ b/src/ngLocale/angular-locale_asa-tz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Kabla yakwe Yethu", + "Baada yakwe Yethu" + ], + "ERAS": [ + "KM", + "BM" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_asa.js b/src/ngLocale/angular-locale_asa.js index c0e074ab0bbf..05e1f0bc8d08 100644 --- a/src/ngLocale/angular-locale_asa.js +++ b/src/ngLocale/angular-locale_asa.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Kabla yakwe Yethu", + "Baada yakwe Yethu" + ], + "ERAS": [ + "KM", + "BM" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_ast-es.js b/src/ngLocale/angular-locale_ast-es.js index 121498bd254d..af513b1a0907 100644 --- a/src/ngLocale/angular-locale_ast-es.js +++ b/src/ngLocale/angular-locale_ast-es.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vienres", "s\u00e1badu" ], + "ERANAMES": [ + "a.C.", + "d.C." + ], + "ERAS": [ + "a.C.", + "d.C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "de xineru", diff --git a/src/ngLocale/angular-locale_ast.js b/src/ngLocale/angular-locale_ast.js index 3c0d1ec41a42..2fc061ee3ca2 100644 --- a/src/ngLocale/angular-locale_ast.js +++ b/src/ngLocale/angular-locale_ast.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vienres", "s\u00e1badu" ], + "ERANAMES": [ + "a.C.", + "d.C." + ], + "ERAS": [ + "a.C.", + "d.C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "de xineru", diff --git a/src/ngLocale/angular-locale_az-cyrl-az.js b/src/ngLocale/angular-locale_az-cyrl-az.js index 3323f916a8fd..ef4956d918df 100644 --- a/src/ngLocale/angular-locale_az-cyrl-az.js +++ b/src/ngLocale/angular-locale_az-cyrl-az.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u04b9\u04af\u043c\u04d9", "\u0448\u04d9\u043d\u0431\u04d9" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0458\u0430\u043d\u0432\u0430\u0440", diff --git a/src/ngLocale/angular-locale_az-cyrl.js b/src/ngLocale/angular-locale_az-cyrl.js index 9ae7f8c565a4..23b1d7c64050 100644 --- a/src/ngLocale/angular-locale_az-cyrl.js +++ b/src/ngLocale/angular-locale_az-cyrl.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u04b9\u04af\u043c\u04d9", "\u0448\u04d9\u043d\u0431\u04d9" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0458\u0430\u043d\u0432\u0430\u0440", diff --git a/src/ngLocale/angular-locale_az-latn-az.js b/src/ngLocale/angular-locale_az-latn-az.js index e8a0d747bf8f..67212d983577 100644 --- a/src/ngLocale/angular-locale_az-latn-az.js +++ b/src/ngLocale/angular-locale_az-latn-az.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "c\u00fcm\u0259", "\u015f\u0259nb\u0259" ], + "ERANAMES": [ + "eram\u0131zdan \u0259vv\u0259l", + "bizim eram\u0131z\u0131n" + ], + "ERAS": [ + "e.\u0259.", + "b.e." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "yanvar", diff --git a/src/ngLocale/angular-locale_az-latn.js b/src/ngLocale/angular-locale_az-latn.js index 6c32fd97ad4a..e72ee1b506de 100644 --- a/src/ngLocale/angular-locale_az-latn.js +++ b/src/ngLocale/angular-locale_az-latn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "c\u00fcm\u0259", "\u015f\u0259nb\u0259" ], + "ERANAMES": [ + "eram\u0131zdan \u0259vv\u0259l", + "bizim eram\u0131z\u0131n" + ], + "ERAS": [ + "e.\u0259.", + "b.e." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "yanvar", diff --git a/src/ngLocale/angular-locale_az.js b/src/ngLocale/angular-locale_az.js index ecf1779585f0..63b8dce1f866 100644 --- a/src/ngLocale/angular-locale_az.js +++ b/src/ngLocale/angular-locale_az.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "c\u00fcm\u0259", "\u015f\u0259nb\u0259" ], + "ERANAMES": [ + "eram\u0131zdan \u0259vv\u0259l", + "bizim eram\u0131z\u0131n" + ], + "ERAS": [ + "e.\u0259.", + "b.e." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "yanvar", diff --git a/src/ngLocale/angular-locale_bas-cm.js b/src/ngLocale/angular-locale_bas-cm.js index 31deceb72928..ccc7ea070a21 100644 --- a/src/ngLocale/angular-locale_bas-cm.js +++ b/src/ngLocale/angular-locale_bas-cm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u014bgw\u00e0 k\u0254\u0254", "\u014bgw\u00e0 j\u00f4n" ], + "ERANAMES": [ + "bis\u016b bi Yes\u00f9 Kr\u01d0st\u00f2", + "i mb\u016bs Yes\u00f9 Kr\u01d0st\u00f2" + ], + "ERAS": [ + "b.Y.K", + "m.Y.K" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "K\u0254nd\u0254\u014b", diff --git a/src/ngLocale/angular-locale_bas.js b/src/ngLocale/angular-locale_bas.js index 6cd66fd63fde..e32cc4208271 100644 --- a/src/ngLocale/angular-locale_bas.js +++ b/src/ngLocale/angular-locale_bas.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u014bgw\u00e0 k\u0254\u0254", "\u014bgw\u00e0 j\u00f4n" ], + "ERANAMES": [ + "bis\u016b bi Yes\u00f9 Kr\u01d0st\u00f2", + "i mb\u016bs Yes\u00f9 Kr\u01d0st\u00f2" + ], + "ERAS": [ + "b.Y.K", + "m.Y.K" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "K\u0254nd\u0254\u014b", diff --git a/src/ngLocale/angular-locale_be-by.js b/src/ngLocale/angular-locale_be-by.js index 2e5acd94108b..fc6a23734e02 100644 --- a/src/ngLocale/angular-locale_be-by.js +++ b/src/ngLocale/angular-locale_be-by.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u044f\u0442\u043d\u0456\u0446\u0430", "\u0441\u0443\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u0434\u0430 \u043d.\u044d.", + "\u043d.\u044d." + ], + "ERAS": [ + "\u0434\u0430 \u043d.\u044d.", + "\u043d.\u044d." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0441\u0442\u0443\u0434\u0437\u0435\u043d\u044f", diff --git a/src/ngLocale/angular-locale_be.js b/src/ngLocale/angular-locale_be.js index abbd8f0bede2..aaafb3326908 100644 --- a/src/ngLocale/angular-locale_be.js +++ b/src/ngLocale/angular-locale_be.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u044f\u0442\u043d\u0456\u0446\u0430", "\u0441\u0443\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u0434\u0430 \u043d.\u044d.", + "\u043d.\u044d." + ], + "ERAS": [ + "\u0434\u0430 \u043d.\u044d.", + "\u043d.\u044d." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0441\u0442\u0443\u0434\u0437\u0435\u043d\u044f", diff --git a/src/ngLocale/angular-locale_bem-zm.js b/src/ngLocale/angular-locale_bem-zm.js index 80ac81836540..96eefdf8054f 100644 --- a/src/ngLocale/angular-locale_bem-zm.js +++ b/src/ngLocale/angular-locale_bem-zm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Palichisano", "Pachibelushi" ], + "ERANAMES": [ + "Before Yesu", + "After Yesu" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_bem.js b/src/ngLocale/angular-locale_bem.js index 2fca17168377..358b0cac33c0 100644 --- a/src/ngLocale/angular-locale_bem.js +++ b/src/ngLocale/angular-locale_bem.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Palichisano", "Pachibelushi" ], + "ERANAMES": [ + "Before Yesu", + "After Yesu" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_bez-tz.js b/src/ngLocale/angular-locale_bez-tz.js index 5d724e1203c0..d8d80a1b28f3 100644 --- a/src/ngLocale/angular-locale_bez-tz.js +++ b/src/ngLocale/angular-locale_bez-tz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "pa hihanu", "pa shahulembela" ], + "ERANAMES": [ + "Kabla ya Mtwaa", + "Baada ya Mtwaa" + ], + "ERAS": [ + "KM", + "BM" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "pa mwedzi gwa hutala", diff --git a/src/ngLocale/angular-locale_bez.js b/src/ngLocale/angular-locale_bez.js index 679024644fea..a240ee9b1aae 100644 --- a/src/ngLocale/angular-locale_bez.js +++ b/src/ngLocale/angular-locale_bez.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "pa hihanu", "pa shahulembela" ], + "ERANAMES": [ + "Kabla ya Mtwaa", + "Baada ya Mtwaa" + ], + "ERAS": [ + "KM", + "BM" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "pa mwedzi gwa hutala", diff --git a/src/ngLocale/angular-locale_bg-bg.js b/src/ngLocale/angular-locale_bg-bg.js index d0e8a699e9a9..984801da0c60 100644 --- a/src/ngLocale/angular-locale_bg-bg.js +++ b/src/ngLocale/angular-locale_bg-bg.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u043f\u0435\u0442\u044a\u043a", "\u0441\u044a\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u043f\u0440\u0435\u0434\u0438 \u0425\u0440\u0438\u0441\u0442\u0430", + "\u0441\u043b\u0435\u0434 \u0425\u0440\u0438\u0441\u0442\u0430" + ], + "ERAS": [ + "\u043f\u0440.\u0425\u0440.", + "\u0441\u043b.\u0425\u0440." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u044f\u043d\u0443\u0430\u0440\u0438", diff --git a/src/ngLocale/angular-locale_bg.js b/src/ngLocale/angular-locale_bg.js index 3a69cb1bb3de..1bfb13282839 100644 --- a/src/ngLocale/angular-locale_bg.js +++ b/src/ngLocale/angular-locale_bg.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u043f\u0435\u0442\u044a\u043a", "\u0441\u044a\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u043f\u0440\u0435\u0434\u0438 \u0425\u0440\u0438\u0441\u0442\u0430", + "\u0441\u043b\u0435\u0434 \u0425\u0440\u0438\u0441\u0442\u0430" + ], + "ERAS": [ + "\u043f\u0440.\u0425\u0440.", + "\u0441\u043b.\u0425\u0440." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u044f\u043d\u0443\u0430\u0440\u0438", diff --git a/src/ngLocale/angular-locale_bm-latn-ml.js b/src/ngLocale/angular-locale_bm-latn-ml.js index 88d1b738f131..c0f62b7887eb 100644 --- a/src/ngLocale/angular-locale_bm-latn-ml.js +++ b/src/ngLocale/angular-locale_bm-latn-ml.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "juma", "sibiri" ], + "ERANAMES": [ + "jezu krisiti \u0272\u025b", + "jezu krisiti mink\u025b" + ], + "ERAS": [ + "J.-C. \u0272\u025b", + "ni J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "zanwuye", diff --git a/src/ngLocale/angular-locale_bm-latn.js b/src/ngLocale/angular-locale_bm-latn.js index 7c71517f3d56..c6faa27fef67 100644 --- a/src/ngLocale/angular-locale_bm-latn.js +++ b/src/ngLocale/angular-locale_bm-latn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "juma", "sibiri" ], + "ERANAMES": [ + "jezu krisiti \u0272\u025b", + "jezu krisiti mink\u025b" + ], + "ERAS": [ + "J.-C. \u0272\u025b", + "ni J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "zanwuye", diff --git a/src/ngLocale/angular-locale_bm.js b/src/ngLocale/angular-locale_bm.js index 651e17d073d9..233863301fdf 100644 --- a/src/ngLocale/angular-locale_bm.js +++ b/src/ngLocale/angular-locale_bm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "juma", "sibiri" ], + "ERANAMES": [ + "jezu krisiti \u0272\u025b", + "jezu krisiti mink\u025b" + ], + "ERAS": [ + "J.-C. \u0272\u025b", + "ni J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "zanwuye", diff --git a/src/ngLocale/angular-locale_bn-bd.js b/src/ngLocale/angular-locale_bn-bd.js index 4242aa7ec9f7..24fb37ae5891 100644 --- a/src/ngLocale/angular-locale_bn-bd.js +++ b/src/ngLocale/angular-locale_bn-bd.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u09b6\u09c1\u0995\u09cd\u09b0\u09ac\u09be\u09b0", "\u09b6\u09a8\u09bf\u09ac\u09be\u09b0" ], + "ERANAMES": [ + "\u0996\u09cd\u09b0\u09bf\u09b8\u09cd\u099f\u09aa\u09c2\u09b0\u09cd\u09ac", + "\u0996\u09c3\u09b7\u09cd\u099f\u09be\u09ac\u09cd\u09a6" + ], + "ERAS": [ + "\u0996\u09cd\u09b0\u09bf\u09b8\u09cd\u099f\u09aa\u09c2\u09b0\u09cd\u09ac", + "\u0996\u09c3\u09b7\u09cd\u099f\u09be\u09ac\u09cd\u09a6" + ], "FIRSTDAYOFWEEK": 4, "MONTH": [ "\u099c\u09be\u09a8\u09c1\u09af\u09bc\u09be\u09b0\u09c0", diff --git a/src/ngLocale/angular-locale_bn-in.js b/src/ngLocale/angular-locale_bn-in.js index eb05d75981bf..63a3c3e6e244 100644 --- a/src/ngLocale/angular-locale_bn-in.js +++ b/src/ngLocale/angular-locale_bn-in.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u09b6\u09c1\u0995\u09cd\u09b0\u09ac\u09be\u09b0", "\u09b6\u09a8\u09bf\u09ac\u09be\u09b0" ], + "ERANAMES": [ + "\u0996\u09cd\u09b0\u09bf\u09b8\u09cd\u099f\u09aa\u09c2\u09b0\u09cd\u09ac", + "\u0996\u09c3\u09b7\u09cd\u099f\u09be\u09ac\u09cd\u09a6" + ], + "ERAS": [ + "\u0996\u09cd\u09b0\u09bf\u09b8\u09cd\u099f\u09aa\u09c2\u09b0\u09cd\u09ac", + "\u0996\u09c3\u09b7\u09cd\u099f\u09be\u09ac\u09cd\u09a6" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u099c\u09be\u09a8\u09c1\u09af\u09bc\u09be\u09b0\u09c0", diff --git a/src/ngLocale/angular-locale_bn.js b/src/ngLocale/angular-locale_bn.js index 510dda8d4a2a..022ce931e250 100644 --- a/src/ngLocale/angular-locale_bn.js +++ b/src/ngLocale/angular-locale_bn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u09b6\u09c1\u0995\u09cd\u09b0\u09ac\u09be\u09b0", "\u09b6\u09a8\u09bf\u09ac\u09be\u09b0" ], + "ERANAMES": [ + "\u0996\u09cd\u09b0\u09bf\u09b8\u09cd\u099f\u09aa\u09c2\u09b0\u09cd\u09ac", + "\u0996\u09c3\u09b7\u09cd\u099f\u09be\u09ac\u09cd\u09a6" + ], + "ERAS": [ + "\u0996\u09cd\u09b0\u09bf\u09b8\u09cd\u099f\u09aa\u09c2\u09b0\u09cd\u09ac", + "\u0996\u09c3\u09b7\u09cd\u099f\u09be\u09ac\u09cd\u09a6" + ], "FIRSTDAYOFWEEK": 4, "MONTH": [ "\u099c\u09be\u09a8\u09c1\u09af\u09bc\u09be\u09b0\u09c0", diff --git a/src/ngLocale/angular-locale_bo-cn.js b/src/ngLocale/angular-locale_bo-cn.js index 9f02012f572f..4bd767a5e322 100644 --- a/src/ngLocale/angular-locale_bo-cn.js +++ b/src/ngLocale/angular-locale_bo-cn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0f42\u0f5f\u0f60\u0f0b\u0f54\u0f0b\u0f66\u0f44\u0f66\u0f0b", "\u0f42\u0f5f\u0f60\u0f0b\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b" ], + "ERANAMES": [ + "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0b\u0f66\u0f94\u0f7c\u0f53\u0f0d", + "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0d" + ], + "ERAS": [ + "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0b\u0f66\u0f94\u0f7c\u0f53\u0f0d", + "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0d" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f44\u0f0b\u0f54\u0f7c\u0f0b", diff --git a/src/ngLocale/angular-locale_bo-in.js b/src/ngLocale/angular-locale_bo-in.js index d0a373cced8a..d8dd95fd7645 100644 --- a/src/ngLocale/angular-locale_bo-in.js +++ b/src/ngLocale/angular-locale_bo-in.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0f42\u0f5f\u0f60\u0f0b\u0f54\u0f0b\u0f66\u0f44\u0f66\u0f0b", "\u0f42\u0f5f\u0f60\u0f0b\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b" ], + "ERANAMES": [ + "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0b\u0f66\u0f94\u0f7c\u0f53\u0f0d", + "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0d" + ], + "ERAS": [ + "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0b\u0f66\u0f94\u0f7c\u0f53\u0f0d", + "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0d" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f44\u0f0b\u0f54\u0f7c\u0f0b", diff --git a/src/ngLocale/angular-locale_bo.js b/src/ngLocale/angular-locale_bo.js index a2e8498b8b20..3df810e23ea3 100644 --- a/src/ngLocale/angular-locale_bo.js +++ b/src/ngLocale/angular-locale_bo.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0f42\u0f5f\u0f60\u0f0b\u0f54\u0f0b\u0f66\u0f44\u0f66\u0f0b", "\u0f42\u0f5f\u0f60\u0f0b\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b" ], + "ERANAMES": [ + "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0b\u0f66\u0f94\u0f7c\u0f53\u0f0d", + "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0d" + ], + "ERAS": [ + "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0b\u0f66\u0f94\u0f7c\u0f53\u0f0d", + "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0d" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f44\u0f0b\u0f54\u0f7c\u0f0b", diff --git a/src/ngLocale/angular-locale_br-fr.js b/src/ngLocale/angular-locale_br-fr.js index bed80d7485f0..111b19cf7800 100644 --- a/src/ngLocale/angular-locale_br-fr.js +++ b/src/ngLocale/angular-locale_br-fr.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Gwener", "Sadorn" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Genver", diff --git a/src/ngLocale/angular-locale_br.js b/src/ngLocale/angular-locale_br.js index d9cd38d57b93..2fbf8714295f 100644 --- a/src/ngLocale/angular-locale_br.js +++ b/src/ngLocale/angular-locale_br.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Gwener", "Sadorn" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Genver", diff --git a/src/ngLocale/angular-locale_brx-in.js b/src/ngLocale/angular-locale_brx-in.js index f37da6682d5c..47c21decce15 100644 --- a/src/ngLocale/angular-locale_brx-in.js +++ b/src/ngLocale/angular-locale_brx-in.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0938\u0941\u0916\u0941\u0930\u092c\u093e\u0930", "\u0938\u0941\u0928\u093f\u092c\u093e\u0930" ], + "ERANAMES": [ + "\u0908\u0938\u093e.\u092a\u0942\u0930\u094d\u0935", + "\u0938\u0928" + ], + "ERAS": [ + "\u0908\u0938\u093e.\u092a\u0942\u0930\u094d\u0935", + "\u0938\u0928" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u091c\u093e\u0928\u0941\u0935\u093e\u0930\u0940", diff --git a/src/ngLocale/angular-locale_brx.js b/src/ngLocale/angular-locale_brx.js index 69a860f0ddd1..29eb02975c4b 100644 --- a/src/ngLocale/angular-locale_brx.js +++ b/src/ngLocale/angular-locale_brx.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0938\u0941\u0916\u0941\u0930\u092c\u093e\u0930", "\u0938\u0941\u0928\u093f\u092c\u093e\u0930" ], + "ERANAMES": [ + "\u0908\u0938\u093e.\u092a\u0942\u0930\u094d\u0935", + "\u0938\u0928" + ], + "ERAS": [ + "\u0908\u0938\u093e.\u092a\u0942\u0930\u094d\u0935", + "\u0938\u0928" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u091c\u093e\u0928\u0941\u0935\u093e\u0930\u0940", diff --git a/src/ngLocale/angular-locale_bs-cyrl-ba.js b/src/ngLocale/angular-locale_bs-cyrl-ba.js index 2c001e6683fe..214cd094026c 100644 --- a/src/ngLocale/angular-locale_bs-cyrl-ba.js +++ b/src/ngLocale/angular-locale_bs-cyrl-ba.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u0435\u0442\u0430\u043a", "\u0441\u0443\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435", + "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435" + ], + "ERAS": [ + "\u043f. \u043d. \u0435.", + "\u043d. \u0435." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0458\u0430\u043d\u0443\u0430\u0440", diff --git a/src/ngLocale/angular-locale_bs-cyrl.js b/src/ngLocale/angular-locale_bs-cyrl.js index 78f6d0adf7dc..dc5579ae4989 100644 --- a/src/ngLocale/angular-locale_bs-cyrl.js +++ b/src/ngLocale/angular-locale_bs-cyrl.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u0435\u0442\u0430\u043a", "\u0441\u0443\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435", + "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435" + ], + "ERAS": [ + "\u043f. \u043d. \u0435.", + "\u043d. \u0435." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0458\u0430\u043d\u0443\u0430\u0440", diff --git a/src/ngLocale/angular-locale_bs-latn-ba.js b/src/ngLocale/angular-locale_bs-latn-ba.js index 6702ab352ee0..f6142e1adc42 100644 --- a/src/ngLocale/angular-locale_bs-latn-ba.js +++ b/src/ngLocale/angular-locale_bs-latn-ba.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "petak", "subota" ], + "ERANAMES": [ + "Prije nove ere", + "Nove ere" + ], + "ERAS": [ + "p. n. e.", + "n. e." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_bs-latn.js b/src/ngLocale/angular-locale_bs-latn.js index ee85ef92e8f9..ab7f2807b7be 100644 --- a/src/ngLocale/angular-locale_bs-latn.js +++ b/src/ngLocale/angular-locale_bs-latn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "petak", "subota" ], + "ERANAMES": [ + "Prije nove ere", + "Nove ere" + ], + "ERAS": [ + "p. n. e.", + "n. e." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_bs.js b/src/ngLocale/angular-locale_bs.js index 8afefc6605a5..779578436de6 100644 --- a/src/ngLocale/angular-locale_bs.js +++ b/src/ngLocale/angular-locale_bs.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "petak", "subota" ], + "ERANAMES": [ + "Prije nove ere", + "Nove ere" + ], + "ERAS": [ + "p. n. e.", + "n. e." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_ca-ad.js b/src/ngLocale/angular-locale_ca-ad.js index edb5a2f475da..8d0b80da73a8 100644 --- a/src/ngLocale/angular-locale_ca-ad.js +++ b/src/ngLocale/angular-locale_ca-ad.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "divendres", "dissabte" ], + "ERANAMES": [ + "abans de Crist", + "despr\u00e9s de Crist" + ], + "ERAS": [ + "aC", + "dC" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "gener", diff --git a/src/ngLocale/angular-locale_ca-es-valencia.js b/src/ngLocale/angular-locale_ca-es-valencia.js index 3da5a8d6b038..24d7bfee2cc1 100644 --- a/src/ngLocale/angular-locale_ca-es-valencia.js +++ b/src/ngLocale/angular-locale_ca-es-valencia.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "divendres", "dissabte" ], + "ERANAMES": [ + "abans de Crist", + "despr\u00e9s de Crist" + ], + "ERAS": [ + "aC", + "dC" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "gener", diff --git a/src/ngLocale/angular-locale_ca-es.js b/src/ngLocale/angular-locale_ca-es.js index 79b298c8c82a..0c04ea9dd9c4 100644 --- a/src/ngLocale/angular-locale_ca-es.js +++ b/src/ngLocale/angular-locale_ca-es.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "divendres", "dissabte" ], + "ERANAMES": [ + "abans de Crist", + "despr\u00e9s de Crist" + ], + "ERAS": [ + "aC", + "dC" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "gener", diff --git a/src/ngLocale/angular-locale_ca-fr.js b/src/ngLocale/angular-locale_ca-fr.js index ea989c0206e5..f087f610311b 100644 --- a/src/ngLocale/angular-locale_ca-fr.js +++ b/src/ngLocale/angular-locale_ca-fr.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "divendres", "dissabte" ], + "ERANAMES": [ + "abans de Crist", + "despr\u00e9s de Crist" + ], + "ERAS": [ + "aC", + "dC" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "gener", diff --git a/src/ngLocale/angular-locale_ca-it.js b/src/ngLocale/angular-locale_ca-it.js index ce283f336549..418ac037cf6e 100644 --- a/src/ngLocale/angular-locale_ca-it.js +++ b/src/ngLocale/angular-locale_ca-it.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "divendres", "dissabte" ], + "ERANAMES": [ + "abans de Crist", + "despr\u00e9s de Crist" + ], + "ERAS": [ + "aC", + "dC" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "gener", diff --git a/src/ngLocale/angular-locale_ca.js b/src/ngLocale/angular-locale_ca.js index e1df17705cef..029e9ebdf3e1 100644 --- a/src/ngLocale/angular-locale_ca.js +++ b/src/ngLocale/angular-locale_ca.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "divendres", "dissabte" ], + "ERANAMES": [ + "abans de Crist", + "despr\u00e9s de Crist" + ], + "ERAS": [ + "aC", + "dC" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "gener", diff --git a/src/ngLocale/angular-locale_cgg-ug.js b/src/ngLocale/angular-locale_cgg-ug.js index 9011e166bbae..95088fef5234 100644 --- a/src/ngLocale/angular-locale_cgg-ug.js +++ b/src/ngLocale/angular-locale_cgg-ug.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Orwakataano", "Orwamukaaga" ], + "ERANAMES": [ + "Kurisito Atakaijire", + "Kurisito Yaijire" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Okwokubanza", diff --git a/src/ngLocale/angular-locale_cgg.js b/src/ngLocale/angular-locale_cgg.js index 701ecd506a49..4c1d7be116bb 100644 --- a/src/ngLocale/angular-locale_cgg.js +++ b/src/ngLocale/angular-locale_cgg.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Orwakataano", "Orwamukaaga" ], + "ERANAMES": [ + "Kurisito Atakaijire", + "Kurisito Yaijire" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Okwokubanza", diff --git a/src/ngLocale/angular-locale_chr-us.js b/src/ngLocale/angular-locale_chr-us.js index 9dbca62b427f..e8956cb0a2f5 100644 --- a/src/ngLocale/angular-locale_chr-us.js +++ b/src/ngLocale/angular-locale_chr-us.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u13e7\u13be\u13a9\u13b6\u13cd\u13d7", "\u13a4\u13be\u13d9\u13d3\u13c8\u13d5\u13be" ], + "ERANAMES": [ + "\u13cf \u13e5\u13cc \u13be\u13d5\u13b2\u13cd\u13ac\u13be", + "\u13a0\u13a9\u13c3\u13ae\u13b5\u13d3\u13cd\u13d7\u13f1 \u13a0\u13d5\u13d8\u13f1\u13cd\u13ac \u13f1\u13b0\u13e9 \u13e7\u13d3\u13c2\u13b8\u13a2\u13cd\u13d7" + ], + "ERAS": [ + "\u13a4\u13d3\u13b7\u13b8", + "\u13a4\u13b6\u13d0\u13c5" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u13a4\u13c3\u13b8\u13d4\u13c5", diff --git a/src/ngLocale/angular-locale_chr.js b/src/ngLocale/angular-locale_chr.js index 74c6a3992e34..aa545386c24e 100644 --- a/src/ngLocale/angular-locale_chr.js +++ b/src/ngLocale/angular-locale_chr.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u13e7\u13be\u13a9\u13b6\u13cd\u13d7", "\u13a4\u13be\u13d9\u13d3\u13c8\u13d5\u13be" ], + "ERANAMES": [ + "\u13cf \u13e5\u13cc \u13be\u13d5\u13b2\u13cd\u13ac\u13be", + "\u13a0\u13a9\u13c3\u13ae\u13b5\u13d3\u13cd\u13d7\u13f1 \u13a0\u13d5\u13d8\u13f1\u13cd\u13ac \u13f1\u13b0\u13e9 \u13e7\u13d3\u13c2\u13b8\u13a2\u13cd\u13d7" + ], + "ERAS": [ + "\u13a4\u13d3\u13b7\u13b8", + "\u13a4\u13b6\u13d0\u13c5" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u13a4\u13c3\u13b8\u13d4\u13c5", diff --git a/src/ngLocale/angular-locale_ckb-arab-iq.js b/src/ngLocale/angular-locale_ckb-arab-iq.js index c2416456a095..7d5ded34ca7c 100644 --- a/src/ngLocale/angular-locale_ckb-arab-iq.js +++ b/src/ngLocale/angular-locale_ckb-arab-iq.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u06be\u06d5\u06cc\u0646\u06cc", "\u0634\u06d5\u0645\u0645\u06d5" ], + "ERANAMES": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646", + "\u0632\u0627\u06cc\u06cc\u0646\u06cc" + ], + "ERAS": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646", + "\u0632" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645", diff --git a/src/ngLocale/angular-locale_ckb-arab-ir.js b/src/ngLocale/angular-locale_ckb-arab-ir.js index 41cac2f2e4dc..a065da2b2005 100644 --- a/src/ngLocale/angular-locale_ckb-arab-ir.js +++ b/src/ngLocale/angular-locale_ckb-arab-ir.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u06be\u06d5\u06cc\u0646\u06cc", "\u0634\u06d5\u0645\u0645\u06d5" ], + "ERANAMES": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646", + "\u0632\u0627\u06cc\u06cc\u0646\u06cc" + ], + "ERAS": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646", + "\u0632" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645", diff --git a/src/ngLocale/angular-locale_ckb-arab.js b/src/ngLocale/angular-locale_ckb-arab.js index 3baba83dc2cc..26372d0e1828 100644 --- a/src/ngLocale/angular-locale_ckb-arab.js +++ b/src/ngLocale/angular-locale_ckb-arab.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u06be\u06d5\u06cc\u0646\u06cc", "\u0634\u06d5\u0645\u0645\u06d5" ], + "ERANAMES": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646", + "\u0632\u0627\u06cc\u06cc\u0646\u06cc" + ], + "ERAS": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646", + "\u0632" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645", diff --git a/src/ngLocale/angular-locale_ckb-iq.js b/src/ngLocale/angular-locale_ckb-iq.js index 9a287afc35e1..c90adb91f252 100644 --- a/src/ngLocale/angular-locale_ckb-iq.js +++ b/src/ngLocale/angular-locale_ckb-iq.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u06be\u06d5\u06cc\u0646\u06cc", "\u0634\u06d5\u0645\u0645\u06d5" ], + "ERANAMES": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646", + "\u0632\u0627\u06cc\u06cc\u0646\u06cc" + ], + "ERAS": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646", + "\u0632" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645", diff --git a/src/ngLocale/angular-locale_ckb-ir.js b/src/ngLocale/angular-locale_ckb-ir.js index 1b963e25ea28..bdc2298d8c20 100644 --- a/src/ngLocale/angular-locale_ckb-ir.js +++ b/src/ngLocale/angular-locale_ckb-ir.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u06be\u06d5\u06cc\u0646\u06cc", "\u0634\u06d5\u0645\u0645\u06d5" ], + "ERANAMES": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646", + "\u0632\u0627\u06cc\u06cc\u0646\u06cc" + ], + "ERAS": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646", + "\u0632" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645", diff --git a/src/ngLocale/angular-locale_ckb-latn-iq.js b/src/ngLocale/angular-locale_ckb-latn-iq.js index 5e2badcc2a90..46596f870ac9 100644 --- a/src/ngLocale/angular-locale_ckb-latn-iq.js +++ b/src/ngLocale/angular-locale_ckb-latn-iq.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u06be\u06d5\u06cc\u0646\u06cc", "\u0634\u06d5\u0645\u0645\u06d5" ], + "ERANAMES": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646", + "\u0632\u0627\u06cc\u06cc\u0646\u06cc" + ], + "ERAS": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646", + "\u0632" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645", diff --git a/src/ngLocale/angular-locale_ckb-latn.js b/src/ngLocale/angular-locale_ckb-latn.js index ed0cfa3189b4..74db728d7019 100644 --- a/src/ngLocale/angular-locale_ckb-latn.js +++ b/src/ngLocale/angular-locale_ckb-latn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u06be\u06d5\u06cc\u0646\u06cc", "\u0634\u06d5\u0645\u0645\u06d5" ], + "ERANAMES": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646", + "\u0632\u0627\u06cc\u06cc\u0646\u06cc" + ], + "ERAS": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646", + "\u0632" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645", diff --git a/src/ngLocale/angular-locale_ckb.js b/src/ngLocale/angular-locale_ckb.js index 13ebcc6331b0..ee828522740e 100644 --- a/src/ngLocale/angular-locale_ckb.js +++ b/src/ngLocale/angular-locale_ckb.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u06be\u06d5\u06cc\u0646\u06cc", "\u0634\u06d5\u0645\u0645\u06d5" ], + "ERANAMES": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646", + "\u0632\u0627\u06cc\u06cc\u0646\u06cc" + ], + "ERAS": [ + "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646", + "\u0632" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645", diff --git a/src/ngLocale/angular-locale_cs-cz.js b/src/ngLocale/angular-locale_cs-cz.js index 4bbb3d4b8f35..d784fef24e83 100644 --- a/src/ngLocale/angular-locale_cs-cz.js +++ b/src/ngLocale/angular-locale_cs-cz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "p\u00e1tek", "sobota" ], + "ERANAMES": [ + "p\u0159. n. l.", + "n. l." + ], + "ERAS": [ + "p\u0159. n. l.", + "n. l." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "ledna", diff --git a/src/ngLocale/angular-locale_cs.js b/src/ngLocale/angular-locale_cs.js index cc4d21298df5..624b761bdb0f 100644 --- a/src/ngLocale/angular-locale_cs.js +++ b/src/ngLocale/angular-locale_cs.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "p\u00e1tek", "sobota" ], + "ERANAMES": [ + "p\u0159. n. l.", + "n. l." + ], + "ERAS": [ + "p\u0159. n. l.", + "n. l." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "ledna", diff --git a/src/ngLocale/angular-locale_cy-gb.js b/src/ngLocale/angular-locale_cy-gb.js index 8eec73a4e1e5..6c1bf8aa81c7 100644 --- a/src/ngLocale/angular-locale_cy-gb.js +++ b/src/ngLocale/angular-locale_cy-gb.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Dydd Gwener", "Dydd Sadwrn" ], + "ERANAMES": [ + "Cyn Crist", + "Oed Crist" + ], + "ERAS": [ + "CC", + "OC" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Ionawr", diff --git a/src/ngLocale/angular-locale_cy.js b/src/ngLocale/angular-locale_cy.js index 47f610d93204..f82259c33fcc 100644 --- a/src/ngLocale/angular-locale_cy.js +++ b/src/ngLocale/angular-locale_cy.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Dydd Gwener", "Dydd Sadwrn" ], + "ERANAMES": [ + "Cyn Crist", + "Oed Crist" + ], + "ERAS": [ + "CC", + "OC" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Ionawr", diff --git a/src/ngLocale/angular-locale_da-dk.js b/src/ngLocale/angular-locale_da-dk.js index 56166ba2a145..3776408ed861 100644 --- a/src/ngLocale/angular-locale_da-dk.js +++ b/src/ngLocale/angular-locale_da-dk.js @@ -47,6 +47,14 @@ $provide.value("$locale", { "fredag", "l\u00f8rdag" ], + "ERANAMES": [ + "f.Kr.", + "e.Kr." + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_da-gl.js b/src/ngLocale/angular-locale_da-gl.js index b2309dbe7a51..2ca2df07de73 100644 --- a/src/ngLocale/angular-locale_da-gl.js +++ b/src/ngLocale/angular-locale_da-gl.js @@ -47,6 +47,14 @@ $provide.value("$locale", { "fredag", "l\u00f8rdag" ], + "ERANAMES": [ + "f.Kr.", + "e.Kr." + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_da.js b/src/ngLocale/angular-locale_da.js index 3c32c5bd1bf4..3da6e4ec07e9 100644 --- a/src/ngLocale/angular-locale_da.js +++ b/src/ngLocale/angular-locale_da.js @@ -47,6 +47,14 @@ $provide.value("$locale", { "fredag", "l\u00f8rdag" ], + "ERANAMES": [ + "f.Kr.", + "e.Kr." + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_dav-ke.js b/src/ngLocale/angular-locale_dav-ke.js index 10e20967b51e..b868eee643e4 100644 --- a/src/ngLocale/angular-locale_dav-ke.js +++ b/src/ngLocale/angular-locale_dav-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Kuramuka kasanu", "Kifula nguwo" ], + "ERANAMES": [ + "Kabla ya Kristo", + "Baada ya Kristo" + ], + "ERAS": [ + "KK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mori ghwa imbiri", diff --git a/src/ngLocale/angular-locale_dav.js b/src/ngLocale/angular-locale_dav.js index 295399b29edf..f172a4500bd7 100644 --- a/src/ngLocale/angular-locale_dav.js +++ b/src/ngLocale/angular-locale_dav.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Kuramuka kasanu", "Kifula nguwo" ], + "ERANAMES": [ + "Kabla ya Kristo", + "Baada ya Kristo" + ], + "ERAS": [ + "KK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mori ghwa imbiri", diff --git a/src/ngLocale/angular-locale_de-at.js b/src/ngLocale/angular-locale_de-at.js index f25b1a70736f..7b060cb32ccd 100644 --- a/src/ngLocale/angular-locale_de-at.js +++ b/src/ngLocale/angular-locale_de-at.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Freitag", "Samstag" ], + "ERANAMES": [ + "v. Chr.", + "n. Chr." + ], + "ERAS": [ + "v. Chr.", + "n. Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "J\u00e4nner", diff --git a/src/ngLocale/angular-locale_de-be.js b/src/ngLocale/angular-locale_de-be.js index d29a9f09ad36..61390da48ef0 100644 --- a/src/ngLocale/angular-locale_de-be.js +++ b/src/ngLocale/angular-locale_de-be.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Freitag", "Samstag" ], + "ERANAMES": [ + "v. Chr.", + "n. Chr." + ], + "ERAS": [ + "v. Chr.", + "n. Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januar", diff --git a/src/ngLocale/angular-locale_de-ch.js b/src/ngLocale/angular-locale_de-ch.js index f904b53a89b7..cdb75cac24c4 100644 --- a/src/ngLocale/angular-locale_de-ch.js +++ b/src/ngLocale/angular-locale_de-ch.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Freitag", "Samstag" ], + "ERANAMES": [ + "v. Chr.", + "n. Chr." + ], + "ERAS": [ + "v. Chr.", + "n. Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januar", diff --git a/src/ngLocale/angular-locale_de-de.js b/src/ngLocale/angular-locale_de-de.js index ffcd14aaeb10..b69252f59d76 100644 --- a/src/ngLocale/angular-locale_de-de.js +++ b/src/ngLocale/angular-locale_de-de.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Freitag", "Samstag" ], + "ERANAMES": [ + "v. Chr.", + "n. Chr." + ], + "ERAS": [ + "v. Chr.", + "n. Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januar", diff --git a/src/ngLocale/angular-locale_de-li.js b/src/ngLocale/angular-locale_de-li.js index baae071c48f7..7b8c5eb18834 100644 --- a/src/ngLocale/angular-locale_de-li.js +++ b/src/ngLocale/angular-locale_de-li.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Freitag", "Samstag" ], + "ERANAMES": [ + "v. Chr.", + "n. Chr." + ], + "ERAS": [ + "v. Chr.", + "n. Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januar", diff --git a/src/ngLocale/angular-locale_de-lu.js b/src/ngLocale/angular-locale_de-lu.js index 85ae41669a2e..f141217c4104 100644 --- a/src/ngLocale/angular-locale_de-lu.js +++ b/src/ngLocale/angular-locale_de-lu.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Freitag", "Samstag" ], + "ERANAMES": [ + "v. Chr.", + "n. Chr." + ], + "ERAS": [ + "v. Chr.", + "n. Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januar", diff --git a/src/ngLocale/angular-locale_de.js b/src/ngLocale/angular-locale_de.js index e9d797636cfc..cbc6643fd5f9 100644 --- a/src/ngLocale/angular-locale_de.js +++ b/src/ngLocale/angular-locale_de.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Freitag", "Samstag" ], + "ERANAMES": [ + "v. Chr.", + "n. Chr." + ], + "ERAS": [ + "v. Chr.", + "n. Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januar", diff --git a/src/ngLocale/angular-locale_dje-ne.js b/src/ngLocale/angular-locale_dje-ne.js index 8d2c2d66bd14..a5f240337f91 100644 --- a/src/ngLocale/angular-locale_dje-ne.js +++ b/src/ngLocale/angular-locale_dje-ne.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Alzuma", "Asibti" ], + "ERANAMES": [ + "Isaa jine", + "Isaa zamanoo" + ], + "ERAS": [ + "IJ", + "IZ" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u017danwiye", diff --git a/src/ngLocale/angular-locale_dje.js b/src/ngLocale/angular-locale_dje.js index b86ee8160ff0..630c9f4a8dbe 100644 --- a/src/ngLocale/angular-locale_dje.js +++ b/src/ngLocale/angular-locale_dje.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Alzuma", "Asibti" ], + "ERANAMES": [ + "Isaa jine", + "Isaa zamanoo" + ], + "ERAS": [ + "IJ", + "IZ" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u017danwiye", diff --git a/src/ngLocale/angular-locale_dsb-de.js b/src/ngLocale/angular-locale_dsb-de.js index 92db4fea5d9c..8d7ca9f29342 100644 --- a/src/ngLocale/angular-locale_dsb-de.js +++ b/src/ngLocale/angular-locale_dsb-de.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "p\u011btk", "sobota" ], + "ERANAMES": [ + "p\u015bed Kristusowym naro\u017aenim", + "p\u00f3 Kristusowem naro\u017aenju" + ], + "ERAS": [ + "p\u015b.Chr.n.", + "p\u00f3 Chr.n." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januara", diff --git a/src/ngLocale/angular-locale_dsb.js b/src/ngLocale/angular-locale_dsb.js index 867434a8880d..f774a75b9449 100644 --- a/src/ngLocale/angular-locale_dsb.js +++ b/src/ngLocale/angular-locale_dsb.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "p\u011btk", "sobota" ], + "ERANAMES": [ + "p\u015bed Kristusowym naro\u017aenim", + "p\u00f3 Kristusowem naro\u017aenju" + ], + "ERAS": [ + "p\u015b.Chr.n.", + "p\u00f3 Chr.n." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januara", diff --git a/src/ngLocale/angular-locale_dua-cm.js b/src/ngLocale/angular-locale_dua-cm.js index aea4e74fd2b1..84d780174695 100644 --- a/src/ngLocale/angular-locale_dua-cm.js +++ b/src/ngLocale/angular-locale_dua-cm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0257\u00f3n\u025bs\u00fa", "esa\u0253as\u00fa" ], + "ERANAMES": [ + "\u0253oso \u0253w\u00e1 y\u00e1\u0253e l\u00e1", + "mb\u00fasa kw\u00e9di a Y\u00e9s" + ], + "ERAS": [ + "\u0253.Ys", + "mb.Ys" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "dim\u0254\u0301di", diff --git a/src/ngLocale/angular-locale_dua.js b/src/ngLocale/angular-locale_dua.js index ff82e734c7b9..c2ffe9450962 100644 --- a/src/ngLocale/angular-locale_dua.js +++ b/src/ngLocale/angular-locale_dua.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0257\u00f3n\u025bs\u00fa", "esa\u0253as\u00fa" ], + "ERANAMES": [ + "\u0253oso \u0253w\u00e1 y\u00e1\u0253e l\u00e1", + "mb\u00fasa kw\u00e9di a Y\u00e9s" + ], + "ERAS": [ + "\u0253.Ys", + "mb.Ys" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "dim\u0254\u0301di", diff --git a/src/ngLocale/angular-locale_dyo-sn.js b/src/ngLocale/angular-locale_dyo-sn.js index fd4ab10d0ee9..e8fadc7142d7 100644 --- a/src/ngLocale/angular-locale_dyo-sn.js +++ b/src/ngLocale/angular-locale_dyo-sn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Arjuma", "Sibiti" ], + "ERANAMES": [ + "Ari\u014buu Yeesu", + "Atoo\u014be Yeesu" + ], + "ERAS": [ + "ArY", + "AtY" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Sanvie", diff --git a/src/ngLocale/angular-locale_dyo.js b/src/ngLocale/angular-locale_dyo.js index 0641e7e15b00..5699f4a208d3 100644 --- a/src/ngLocale/angular-locale_dyo.js +++ b/src/ngLocale/angular-locale_dyo.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Arjuma", "Sibiti" ], + "ERANAMES": [ + "Ari\u014buu Yeesu", + "Atoo\u014be Yeesu" + ], + "ERAS": [ + "ArY", + "AtY" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Sanvie", diff --git a/src/ngLocale/angular-locale_dz-bt.js b/src/ngLocale/angular-locale_dz-bt.js index 10772edb11ea..86b70825bd56 100644 --- a/src/ngLocale/angular-locale_dz-bt.js +++ b/src/ngLocale/angular-locale_dz-bt.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0f42\u0f5f\u0f60\u0f0b\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b", "\u0f42\u0f5f\u0f60\u0f0b\u0f49\u0f72\u0f0b\u0f58\u0f0b" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0f5f\u0fb3\u0f0b\u0f51\u0f44\u0f54\u0f0b", diff --git a/src/ngLocale/angular-locale_dz.js b/src/ngLocale/angular-locale_dz.js index 979bab454ef7..884e0ed00835 100644 --- a/src/ngLocale/angular-locale_dz.js +++ b/src/ngLocale/angular-locale_dz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0f42\u0f5f\u0f60\u0f0b\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b", "\u0f42\u0f5f\u0f60\u0f0b\u0f49\u0f72\u0f0b\u0f58\u0f0b" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0f5f\u0fb3\u0f0b\u0f51\u0f44\u0f54\u0f0b", diff --git a/src/ngLocale/angular-locale_ebu-ke.js b/src/ngLocale/angular-locale_ebu-ke.js index 1e71f9e51491..d55804f2abef 100644 --- a/src/ngLocale/angular-locale_ebu-ke.js +++ b/src/ngLocale/angular-locale_ebu-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Njumaa", "NJumamothii" ], + "ERANAMES": [ + "Mbere ya Kristo", + "Thutha wa Kristo" + ], + "ERAS": [ + "MK", + "TK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mweri wa mbere", diff --git a/src/ngLocale/angular-locale_ebu.js b/src/ngLocale/angular-locale_ebu.js index c64359eb7244..4d6bf04f484b 100644 --- a/src/ngLocale/angular-locale_ebu.js +++ b/src/ngLocale/angular-locale_ebu.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Njumaa", "NJumamothii" ], + "ERANAMES": [ + "Mbere ya Kristo", + "Thutha wa Kristo" + ], + "ERAS": [ + "MK", + "TK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mweri wa mbere", diff --git a/src/ngLocale/angular-locale_ee-gh.js b/src/ngLocale/angular-locale_ee-gh.js index 8b7c6f5d00ab..2ee22efde1de 100644 --- a/src/ngLocale/angular-locale_ee-gh.js +++ b/src/ngLocale/angular-locale_ee-gh.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "fi\u0256a", "memle\u0256a" ], + "ERANAMES": [ + "Hafi Yesu Va Do \u014bg\u0254", + "Yesu \u014a\u0254li" + ], + "ERAS": [ + "hY", + "Y\u014b" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "dzove", diff --git a/src/ngLocale/angular-locale_ee-tg.js b/src/ngLocale/angular-locale_ee-tg.js index f95f16760fb1..fdf60c13ff29 100644 --- a/src/ngLocale/angular-locale_ee-tg.js +++ b/src/ngLocale/angular-locale_ee-tg.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "fi\u0256a", "memle\u0256a" ], + "ERANAMES": [ + "Hafi Yesu Va Do \u014bg\u0254", + "Yesu \u014a\u0254li" + ], + "ERAS": [ + "hY", + "Y\u014b" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "dzove", diff --git a/src/ngLocale/angular-locale_ee.js b/src/ngLocale/angular-locale_ee.js index 5706ed89147e..ab435ba03662 100644 --- a/src/ngLocale/angular-locale_ee.js +++ b/src/ngLocale/angular-locale_ee.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "fi\u0256a", "memle\u0256a" ], + "ERANAMES": [ + "Hafi Yesu Va Do \u014bg\u0254", + "Yesu \u014a\u0254li" + ], + "ERAS": [ + "hY", + "Y\u014b" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "dzove", diff --git a/src/ngLocale/angular-locale_el-cy.js b/src/ngLocale/angular-locale_el-cy.js index 9479d5818ace..220b50607655 100644 --- a/src/ngLocale/angular-locale_el-cy.js +++ b/src/ngLocale/angular-locale_el-cy.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u03a0\u03b1\u03c1\u03b1\u03c3\u03ba\u03b5\u03c5\u03ae", "\u03a3\u03ac\u03b2\u03b2\u03b1\u03c4\u03bf" ], + "ERANAMES": [ + "\u03c0\u03c1\u03bf \u03a7\u03c1\u03b9\u03c3\u03c4\u03bf\u03cd", + "\u03bc\u03b5\u03c4\u03ac \u03a7\u03c1\u03b9\u03c3\u03c4\u03cc\u03bd" + ], + "ERAS": [ + "\u03c0.\u03a7.", + "\u03bc.\u03a7." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0399\u03b1\u03bd\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5", diff --git a/src/ngLocale/angular-locale_el-gr.js b/src/ngLocale/angular-locale_el-gr.js index 9fda52f56b98..72c8b719b93c 100644 --- a/src/ngLocale/angular-locale_el-gr.js +++ b/src/ngLocale/angular-locale_el-gr.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u03a0\u03b1\u03c1\u03b1\u03c3\u03ba\u03b5\u03c5\u03ae", "\u03a3\u03ac\u03b2\u03b2\u03b1\u03c4\u03bf" ], + "ERANAMES": [ + "\u03c0\u03c1\u03bf \u03a7\u03c1\u03b9\u03c3\u03c4\u03bf\u03cd", + "\u03bc\u03b5\u03c4\u03ac \u03a7\u03c1\u03b9\u03c3\u03c4\u03cc\u03bd" + ], + "ERAS": [ + "\u03c0.\u03a7.", + "\u03bc.\u03a7." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0399\u03b1\u03bd\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5", diff --git a/src/ngLocale/angular-locale_el.js b/src/ngLocale/angular-locale_el.js index 5c1927e49521..216542b8755e 100644 --- a/src/ngLocale/angular-locale_el.js +++ b/src/ngLocale/angular-locale_el.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u03a0\u03b1\u03c1\u03b1\u03c3\u03ba\u03b5\u03c5\u03ae", "\u03a3\u03ac\u03b2\u03b2\u03b1\u03c4\u03bf" ], + "ERANAMES": [ + "\u03c0\u03c1\u03bf \u03a7\u03c1\u03b9\u03c3\u03c4\u03bf\u03cd", + "\u03bc\u03b5\u03c4\u03ac \u03a7\u03c1\u03b9\u03c3\u03c4\u03cc\u03bd" + ], + "ERAS": [ + "\u03c0.\u03a7.", + "\u03bc.\u03a7." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0399\u03b1\u03bd\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5", diff --git a/src/ngLocale/angular-locale_en-001.js b/src/ngLocale/angular-locale_en-001.js index 3adb7b07bc2d..85b2db6c7ad2 100644 --- a/src/ngLocale/angular-locale_en-001.js +++ b/src/ngLocale/angular-locale_en-001.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-150.js b/src/ngLocale/angular-locale_en-150.js index 2a828965c2a6..0985201fc823 100644 --- a/src/ngLocale/angular-locale_en-150.js +++ b/src/ngLocale/angular-locale_en-150.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-ag.js b/src/ngLocale/angular-locale_en-ag.js index 71f43aaa852b..514f81b2b661 100644 --- a/src/ngLocale/angular-locale_en-ag.js +++ b/src/ngLocale/angular-locale_en-ag.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-ai.js b/src/ngLocale/angular-locale_en-ai.js index 7d46b3d11446..e571e35ee1ed 100644 --- a/src/ngLocale/angular-locale_en-ai.js +++ b/src/ngLocale/angular-locale_en-ai.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-as.js b/src/ngLocale/angular-locale_en-as.js index ea85bc278cb0..0f43e1eee61d 100644 --- a/src/ngLocale/angular-locale_en-as.js +++ b/src/ngLocale/angular-locale_en-as.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-au.js b/src/ngLocale/angular-locale_en-au.js index 2e2429a5d19a..77297d5e619d 100644 --- a/src/ngLocale/angular-locale_en-au.js +++ b/src/ngLocale/angular-locale_en-au.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-bb.js b/src/ngLocale/angular-locale_en-bb.js index f420e8588efb..e650cbaf89e2 100644 --- a/src/ngLocale/angular-locale_en-bb.js +++ b/src/ngLocale/angular-locale_en-bb.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-be.js b/src/ngLocale/angular-locale_en-be.js index 88d0fa8e2e55..d874ddc25337 100644 --- a/src/ngLocale/angular-locale_en-be.js +++ b/src/ngLocale/angular-locale_en-be.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-bm.js b/src/ngLocale/angular-locale_en-bm.js index a9a2b575d820..cbdb7909aaa2 100644 --- a/src/ngLocale/angular-locale_en-bm.js +++ b/src/ngLocale/angular-locale_en-bm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-bs.js b/src/ngLocale/angular-locale_en-bs.js index 39d4b516e1ff..29c844e2cfff 100644 --- a/src/ngLocale/angular-locale_en-bs.js +++ b/src/ngLocale/angular-locale_en-bs.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-bw.js b/src/ngLocale/angular-locale_en-bw.js index 02329406769e..c0a75c87ac14 100644 --- a/src/ngLocale/angular-locale_en-bw.js +++ b/src/ngLocale/angular-locale_en-bw.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-bz.js b/src/ngLocale/angular-locale_en-bz.js index 1f2140ae4e3c..1300d6d0ff81 100644 --- a/src/ngLocale/angular-locale_en-bz.js +++ b/src/ngLocale/angular-locale_en-bz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-ca.js b/src/ngLocale/angular-locale_en-ca.js index 81400f316a8a..18bbe3bae4ca 100644 --- a/src/ngLocale/angular-locale_en-ca.js +++ b/src/ngLocale/angular-locale_en-ca.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-cc.js b/src/ngLocale/angular-locale_en-cc.js index 32ebf1b27377..d3b6d1a5b84f 100644 --- a/src/ngLocale/angular-locale_en-cc.js +++ b/src/ngLocale/angular-locale_en-cc.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-ck.js b/src/ngLocale/angular-locale_en-ck.js index 4f8370fcb9fd..335b38f2fa3e 100644 --- a/src/ngLocale/angular-locale_en-ck.js +++ b/src/ngLocale/angular-locale_en-ck.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-cm.js b/src/ngLocale/angular-locale_en-cm.js index 6edc9d25cabb..2880a03bbe1c 100644 --- a/src/ngLocale/angular-locale_en-cm.js +++ b/src/ngLocale/angular-locale_en-cm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-cx.js b/src/ngLocale/angular-locale_en-cx.js index ea2a20cfa85b..018c922fb7b7 100644 --- a/src/ngLocale/angular-locale_en-cx.js +++ b/src/ngLocale/angular-locale_en-cx.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-dg.js b/src/ngLocale/angular-locale_en-dg.js index 6dab571902dc..6aa3e1e0ec00 100644 --- a/src/ngLocale/angular-locale_en-dg.js +++ b/src/ngLocale/angular-locale_en-dg.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-dm.js b/src/ngLocale/angular-locale_en-dm.js index 2817c0af5236..52ca9f334d92 100644 --- a/src/ngLocale/angular-locale_en-dm.js +++ b/src/ngLocale/angular-locale_en-dm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-er.js b/src/ngLocale/angular-locale_en-er.js index 9d3abe29c11d..7323d055cbdf 100644 --- a/src/ngLocale/angular-locale_en-er.js +++ b/src/ngLocale/angular-locale_en-er.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-fj.js b/src/ngLocale/angular-locale_en-fj.js index 650b7e6a42a4..094a90ffeaf6 100644 --- a/src/ngLocale/angular-locale_en-fj.js +++ b/src/ngLocale/angular-locale_en-fj.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-fk.js b/src/ngLocale/angular-locale_en-fk.js index fe43da78e783..ba8fdea4cae3 100644 --- a/src/ngLocale/angular-locale_en-fk.js +++ b/src/ngLocale/angular-locale_en-fk.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-fm.js b/src/ngLocale/angular-locale_en-fm.js index b57f9595f3a7..c4330b80ab60 100644 --- a/src/ngLocale/angular-locale_en-fm.js +++ b/src/ngLocale/angular-locale_en-fm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-gb.js b/src/ngLocale/angular-locale_en-gb.js index a405ecd1e346..889352b214a4 100644 --- a/src/ngLocale/angular-locale_en-gb.js +++ b/src/ngLocale/angular-locale_en-gb.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-gd.js b/src/ngLocale/angular-locale_en-gd.js index cbec93fabf7a..540bad52ab55 100644 --- a/src/ngLocale/angular-locale_en-gd.js +++ b/src/ngLocale/angular-locale_en-gd.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-gg.js b/src/ngLocale/angular-locale_en-gg.js index c1720f3a72a8..a574288cdb8d 100644 --- a/src/ngLocale/angular-locale_en-gg.js +++ b/src/ngLocale/angular-locale_en-gg.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-gh.js b/src/ngLocale/angular-locale_en-gh.js index 0214bb2e3dc5..272b3ec2cc19 100644 --- a/src/ngLocale/angular-locale_en-gh.js +++ b/src/ngLocale/angular-locale_en-gh.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-gi.js b/src/ngLocale/angular-locale_en-gi.js index 9280fd362fa7..3f3496c32419 100644 --- a/src/ngLocale/angular-locale_en-gi.js +++ b/src/ngLocale/angular-locale_en-gi.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-gm.js b/src/ngLocale/angular-locale_en-gm.js index 1bf59162fdb8..c56427c39738 100644 --- a/src/ngLocale/angular-locale_en-gm.js +++ b/src/ngLocale/angular-locale_en-gm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-gu.js b/src/ngLocale/angular-locale_en-gu.js index 63689aaa01dd..4c3501b7cfc6 100644 --- a/src/ngLocale/angular-locale_en-gu.js +++ b/src/ngLocale/angular-locale_en-gu.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-gy.js b/src/ngLocale/angular-locale_en-gy.js index 241112994258..297a607fbb2b 100644 --- a/src/ngLocale/angular-locale_en-gy.js +++ b/src/ngLocale/angular-locale_en-gy.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-hk.js b/src/ngLocale/angular-locale_en-hk.js index 5630094d670c..cac44a37701d 100644 --- a/src/ngLocale/angular-locale_en-hk.js +++ b/src/ngLocale/angular-locale_en-hk.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-ie.js b/src/ngLocale/angular-locale_en-ie.js index a9bbc8c3b817..ad202ff1481b 100644 --- a/src/ngLocale/angular-locale_en-ie.js +++ b/src/ngLocale/angular-locale_en-ie.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-im.js b/src/ngLocale/angular-locale_en-im.js index e07ee3ca2342..247592d15974 100644 --- a/src/ngLocale/angular-locale_en-im.js +++ b/src/ngLocale/angular-locale_en-im.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-in.js b/src/ngLocale/angular-locale_en-in.js index 62cc046f888e..5af019f7033c 100644 --- a/src/ngLocale/angular-locale_en-in.js +++ b/src/ngLocale/angular-locale_en-in.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-io.js b/src/ngLocale/angular-locale_en-io.js index fb9eef5c6f0d..f1ee01903349 100644 --- a/src/ngLocale/angular-locale_en-io.js +++ b/src/ngLocale/angular-locale_en-io.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-iso.js b/src/ngLocale/angular-locale_en-iso.js index 1a05c28f1612..09673542f35d 100644 --- a/src/ngLocale/angular-locale_en-iso.js +++ b/src/ngLocale/angular-locale_en-iso.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-je.js b/src/ngLocale/angular-locale_en-je.js index 1cccfdc9bb5c..93cd502df5a2 100644 --- a/src/ngLocale/angular-locale_en-je.js +++ b/src/ngLocale/angular-locale_en-je.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-jm.js b/src/ngLocale/angular-locale_en-jm.js index 976792be38e6..8714fa58c8ff 100644 --- a/src/ngLocale/angular-locale_en-jm.js +++ b/src/ngLocale/angular-locale_en-jm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-ke.js b/src/ngLocale/angular-locale_en-ke.js index 16698a60d99d..27fcf9c3d4be 100644 --- a/src/ngLocale/angular-locale_en-ke.js +++ b/src/ngLocale/angular-locale_en-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-ki.js b/src/ngLocale/angular-locale_en-ki.js index 7b2186cdfd8c..d44fe8afd85c 100644 --- a/src/ngLocale/angular-locale_en-ki.js +++ b/src/ngLocale/angular-locale_en-ki.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-kn.js b/src/ngLocale/angular-locale_en-kn.js index f0669d51d44c..6c3be669ec67 100644 --- a/src/ngLocale/angular-locale_en-kn.js +++ b/src/ngLocale/angular-locale_en-kn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-ky.js b/src/ngLocale/angular-locale_en-ky.js index 3f068f7d7f2c..2acdbe6f9329 100644 --- a/src/ngLocale/angular-locale_en-ky.js +++ b/src/ngLocale/angular-locale_en-ky.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-lc.js b/src/ngLocale/angular-locale_en-lc.js index 1a59dc2987ff..29b119b70e9a 100644 --- a/src/ngLocale/angular-locale_en-lc.js +++ b/src/ngLocale/angular-locale_en-lc.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-lr.js b/src/ngLocale/angular-locale_en-lr.js index 7b2750b41811..837e0da082b7 100644 --- a/src/ngLocale/angular-locale_en-lr.js +++ b/src/ngLocale/angular-locale_en-lr.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-ls.js b/src/ngLocale/angular-locale_en-ls.js index acbca7c85540..7e9bb5b4b47e 100644 --- a/src/ngLocale/angular-locale_en-ls.js +++ b/src/ngLocale/angular-locale_en-ls.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-mg.js b/src/ngLocale/angular-locale_en-mg.js index 8c10f47a37f3..a40570de8913 100644 --- a/src/ngLocale/angular-locale_en-mg.js +++ b/src/ngLocale/angular-locale_en-mg.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-mh.js b/src/ngLocale/angular-locale_en-mh.js index 3d575ad0db9c..b255f4abda1a 100644 --- a/src/ngLocale/angular-locale_en-mh.js +++ b/src/ngLocale/angular-locale_en-mh.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-mo.js b/src/ngLocale/angular-locale_en-mo.js index 7a2b2e428d3c..a45a7aea2469 100644 --- a/src/ngLocale/angular-locale_en-mo.js +++ b/src/ngLocale/angular-locale_en-mo.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-mp.js b/src/ngLocale/angular-locale_en-mp.js index d7be15a39bdf..a76845950840 100644 --- a/src/ngLocale/angular-locale_en-mp.js +++ b/src/ngLocale/angular-locale_en-mp.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-ms.js b/src/ngLocale/angular-locale_en-ms.js index 656610cb0a63..eb5e66d6757f 100644 --- a/src/ngLocale/angular-locale_en-ms.js +++ b/src/ngLocale/angular-locale_en-ms.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-mt.js b/src/ngLocale/angular-locale_en-mt.js index e2ec5d352bd3..f9caa32a1da0 100644 --- a/src/ngLocale/angular-locale_en-mt.js +++ b/src/ngLocale/angular-locale_en-mt.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-mu.js b/src/ngLocale/angular-locale_en-mu.js index 4eef66950e5b..dd9b37235a83 100644 --- a/src/ngLocale/angular-locale_en-mu.js +++ b/src/ngLocale/angular-locale_en-mu.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-mw.js b/src/ngLocale/angular-locale_en-mw.js index e5d7d9d56cf9..b614f78cfe8b 100644 --- a/src/ngLocale/angular-locale_en-mw.js +++ b/src/ngLocale/angular-locale_en-mw.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-my.js b/src/ngLocale/angular-locale_en-my.js index fa0063e9f883..1c20c109f946 100644 --- a/src/ngLocale/angular-locale_en-my.js +++ b/src/ngLocale/angular-locale_en-my.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-na.js b/src/ngLocale/angular-locale_en-na.js index 62f875917757..6f9c11e81ad1 100644 --- a/src/ngLocale/angular-locale_en-na.js +++ b/src/ngLocale/angular-locale_en-na.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-nf.js b/src/ngLocale/angular-locale_en-nf.js index b95d73fe2f9c..a79a7df70503 100644 --- a/src/ngLocale/angular-locale_en-nf.js +++ b/src/ngLocale/angular-locale_en-nf.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-ng.js b/src/ngLocale/angular-locale_en-ng.js index 1419023d3ed7..cd0b9d7df762 100644 --- a/src/ngLocale/angular-locale_en-ng.js +++ b/src/ngLocale/angular-locale_en-ng.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-nr.js b/src/ngLocale/angular-locale_en-nr.js index 29149bc9e038..04c30929e31a 100644 --- a/src/ngLocale/angular-locale_en-nr.js +++ b/src/ngLocale/angular-locale_en-nr.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-nu.js b/src/ngLocale/angular-locale_en-nu.js index b257c1488054..6d0f92986a0a 100644 --- a/src/ngLocale/angular-locale_en-nu.js +++ b/src/ngLocale/angular-locale_en-nu.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-nz.js b/src/ngLocale/angular-locale_en-nz.js index 9e390af33c83..e254d7d76bd4 100644 --- a/src/ngLocale/angular-locale_en-nz.js +++ b/src/ngLocale/angular-locale_en-nz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-pg.js b/src/ngLocale/angular-locale_en-pg.js index b1f72b18830e..9377d82e2e13 100644 --- a/src/ngLocale/angular-locale_en-pg.js +++ b/src/ngLocale/angular-locale_en-pg.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-ph.js b/src/ngLocale/angular-locale_en-ph.js index 53ccc259ca17..a7a63035057a 100644 --- a/src/ngLocale/angular-locale_en-ph.js +++ b/src/ngLocale/angular-locale_en-ph.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-pk.js b/src/ngLocale/angular-locale_en-pk.js index d52d1927081b..46603f114d69 100644 --- a/src/ngLocale/angular-locale_en-pk.js +++ b/src/ngLocale/angular-locale_en-pk.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-pn.js b/src/ngLocale/angular-locale_en-pn.js index 5ad4b113c75d..5c3c028148eb 100644 --- a/src/ngLocale/angular-locale_en-pn.js +++ b/src/ngLocale/angular-locale_en-pn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-pr.js b/src/ngLocale/angular-locale_en-pr.js index 41cfb9b34b5d..6fa7bf5950d5 100644 --- a/src/ngLocale/angular-locale_en-pr.js +++ b/src/ngLocale/angular-locale_en-pr.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-pw.js b/src/ngLocale/angular-locale_en-pw.js index 092469ad11b5..a3c05e749061 100644 --- a/src/ngLocale/angular-locale_en-pw.js +++ b/src/ngLocale/angular-locale_en-pw.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-rw.js b/src/ngLocale/angular-locale_en-rw.js index b3d58c782230..7b98c34cff24 100644 --- a/src/ngLocale/angular-locale_en-rw.js +++ b/src/ngLocale/angular-locale_en-rw.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-sb.js b/src/ngLocale/angular-locale_en-sb.js index e17a3469df0b..5ba214e75963 100644 --- a/src/ngLocale/angular-locale_en-sb.js +++ b/src/ngLocale/angular-locale_en-sb.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-sc.js b/src/ngLocale/angular-locale_en-sc.js index 518645e809a9..7034e4f651d0 100644 --- a/src/ngLocale/angular-locale_en-sc.js +++ b/src/ngLocale/angular-locale_en-sc.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-sd.js b/src/ngLocale/angular-locale_en-sd.js index d82fb7dd7fb5..42942d50fe54 100644 --- a/src/ngLocale/angular-locale_en-sd.js +++ b/src/ngLocale/angular-locale_en-sd.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-sg.js b/src/ngLocale/angular-locale_en-sg.js index 400b918dc165..c205723df0f0 100644 --- a/src/ngLocale/angular-locale_en-sg.js +++ b/src/ngLocale/angular-locale_en-sg.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-sh.js b/src/ngLocale/angular-locale_en-sh.js index de9bb47c7c07..cf63e2b2bbaa 100644 --- a/src/ngLocale/angular-locale_en-sh.js +++ b/src/ngLocale/angular-locale_en-sh.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-sl.js b/src/ngLocale/angular-locale_en-sl.js index ab814072e3d2..761af77943cb 100644 --- a/src/ngLocale/angular-locale_en-sl.js +++ b/src/ngLocale/angular-locale_en-sl.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-ss.js b/src/ngLocale/angular-locale_en-ss.js index 60f795ba0489..12df4eb3ea1d 100644 --- a/src/ngLocale/angular-locale_en-ss.js +++ b/src/ngLocale/angular-locale_en-ss.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-sx.js b/src/ngLocale/angular-locale_en-sx.js index c7f39aed3155..aac389b3328d 100644 --- a/src/ngLocale/angular-locale_en-sx.js +++ b/src/ngLocale/angular-locale_en-sx.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-sz.js b/src/ngLocale/angular-locale_en-sz.js index 45280510372d..0c7b7a2685c4 100644 --- a/src/ngLocale/angular-locale_en-sz.js +++ b/src/ngLocale/angular-locale_en-sz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-tc.js b/src/ngLocale/angular-locale_en-tc.js index 4f161f8ebd39..33932cd423ae 100644 --- a/src/ngLocale/angular-locale_en-tc.js +++ b/src/ngLocale/angular-locale_en-tc.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-tk.js b/src/ngLocale/angular-locale_en-tk.js index 01051ab24a20..2fc6797bbaee 100644 --- a/src/ngLocale/angular-locale_en-tk.js +++ b/src/ngLocale/angular-locale_en-tk.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-to.js b/src/ngLocale/angular-locale_en-to.js index ffb45d8fc56b..fd1e58d89c80 100644 --- a/src/ngLocale/angular-locale_en-to.js +++ b/src/ngLocale/angular-locale_en-to.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-tt.js b/src/ngLocale/angular-locale_en-tt.js index c7ffd5d4dc2a..b32cf15d996b 100644 --- a/src/ngLocale/angular-locale_en-tt.js +++ b/src/ngLocale/angular-locale_en-tt.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-tv.js b/src/ngLocale/angular-locale_en-tv.js index fad893685a72..e86caaf8dd28 100644 --- a/src/ngLocale/angular-locale_en-tv.js +++ b/src/ngLocale/angular-locale_en-tv.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-tz.js b/src/ngLocale/angular-locale_en-tz.js index e66ef9d2805e..69a4df4c2486 100644 --- a/src/ngLocale/angular-locale_en-tz.js +++ b/src/ngLocale/angular-locale_en-tz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-ug.js b/src/ngLocale/angular-locale_en-ug.js index 5f05abf587fd..519515468ba3 100644 --- a/src/ngLocale/angular-locale_en-ug.js +++ b/src/ngLocale/angular-locale_en-ug.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-um.js b/src/ngLocale/angular-locale_en-um.js index 59b966a5953e..9c6e88a88ecd 100644 --- a/src/ngLocale/angular-locale_en-um.js +++ b/src/ngLocale/angular-locale_en-um.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-us.js b/src/ngLocale/angular-locale_en-us.js index b60a175818ea..861abecdf591 100644 --- a/src/ngLocale/angular-locale_en-us.js +++ b/src/ngLocale/angular-locale_en-us.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-vc.js b/src/ngLocale/angular-locale_en-vc.js index 2d62c1ec54d6..4b8426984d36 100644 --- a/src/ngLocale/angular-locale_en-vc.js +++ b/src/ngLocale/angular-locale_en-vc.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-vg.js b/src/ngLocale/angular-locale_en-vg.js index 2d8b0e468e9d..4c9180058ef7 100644 --- a/src/ngLocale/angular-locale_en-vg.js +++ b/src/ngLocale/angular-locale_en-vg.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-vi.js b/src/ngLocale/angular-locale_en-vi.js index 33242ed20557..fa0746d748c9 100644 --- a/src/ngLocale/angular-locale_en-vi.js +++ b/src/ngLocale/angular-locale_en-vi.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-vu.js b/src/ngLocale/angular-locale_en-vu.js index a7b4790e3f62..dc462e842977 100644 --- a/src/ngLocale/angular-locale_en-vu.js +++ b/src/ngLocale/angular-locale_en-vu.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-ws.js b/src/ngLocale/angular-locale_en-ws.js index e797ea05ec13..9da27d23bab6 100644 --- a/src/ngLocale/angular-locale_en-ws.js +++ b/src/ngLocale/angular-locale_en-ws.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-za.js b/src/ngLocale/angular-locale_en-za.js index ccc369404927..0cb3f8d87d49 100644 --- a/src/ngLocale/angular-locale_en-za.js +++ b/src/ngLocale/angular-locale_en-za.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-zm.js b/src/ngLocale/angular-locale_en-zm.js index c66d5c44ddd3..7c8e7d0efd33 100644 --- a/src/ngLocale/angular-locale_en-zm.js +++ b/src/ngLocale/angular-locale_en-zm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en-zw.js b/src/ngLocale/angular-locale_en-zw.js index fe54d754e5c8..0ad6ed453c70 100644 --- a/src/ngLocale/angular-locale_en-zw.js +++ b/src/ngLocale/angular-locale_en-zw.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_en.js b/src/ngLocale/angular-locale_en.js index 4c0a35a5a4f5..efcf9b0efeca 100644 --- a/src/ngLocale/angular-locale_en.js +++ b/src/ngLocale/angular-locale_en.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friday", "Saturday" ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "January", diff --git a/src/ngLocale/angular-locale_eo-001.js b/src/ngLocale/angular-locale_eo-001.js index 434608f26967..ede4557176a3 100644 --- a/src/ngLocale/angular-locale_eo-001.js +++ b/src/ngLocale/angular-locale_eo-001.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vendredo", "sabato" ], + "ERANAMES": [ + "aK", + "pK" + ], + "ERAS": [ + "aK", + "pK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januaro", diff --git a/src/ngLocale/angular-locale_eo.js b/src/ngLocale/angular-locale_eo.js index 46f92f0529d2..bfd7031a7895 100644 --- a/src/ngLocale/angular-locale_eo.js +++ b/src/ngLocale/angular-locale_eo.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vendredo", "sabato" ], + "ERANAMES": [ + "aK", + "pK" + ], + "ERAS": [ + "aK", + "pK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januaro", diff --git a/src/ngLocale/angular-locale_es-419.js b/src/ngLocale/angular-locale_es-419.js index d28b6a2a35e4..2433214e2faa 100644 --- a/src/ngLocale/angular-locale_es-419.js +++ b/src/ngLocale/angular-locale_es-419.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-ar.js b/src/ngLocale/angular-locale_es-ar.js index 74c68c4a264e..ea27d732a8ca 100644 --- a/src/ngLocale/angular-locale_es-ar.js +++ b/src/ngLocale/angular-locale_es-ar.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-bo.js b/src/ngLocale/angular-locale_es-bo.js index 84efaaf4ffc7..635a04b5058c 100644 --- a/src/ngLocale/angular-locale_es-bo.js +++ b/src/ngLocale/angular-locale_es-bo.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-cl.js b/src/ngLocale/angular-locale_es-cl.js index f50755574277..fb137fbdc1a0 100644 --- a/src/ngLocale/angular-locale_es-cl.js +++ b/src/ngLocale/angular-locale_es-cl.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-co.js b/src/ngLocale/angular-locale_es-co.js index 0e3479765f9e..914f2e4eb250 100644 --- a/src/ngLocale/angular-locale_es-co.js +++ b/src/ngLocale/angular-locale_es-co.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-cr.js b/src/ngLocale/angular-locale_es-cr.js index 42a6a2952b44..56d693300e72 100644 --- a/src/ngLocale/angular-locale_es-cr.js +++ b/src/ngLocale/angular-locale_es-cr.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-cu.js b/src/ngLocale/angular-locale_es-cu.js index cc72c3e3786c..9e14bd78e94a 100644 --- a/src/ngLocale/angular-locale_es-cu.js +++ b/src/ngLocale/angular-locale_es-cu.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-do.js b/src/ngLocale/angular-locale_es-do.js index 974bc7637f9b..93653c95cb3c 100644 --- a/src/ngLocale/angular-locale_es-do.js +++ b/src/ngLocale/angular-locale_es-do.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-ea.js b/src/ngLocale/angular-locale_es-ea.js index bf64016f2ea7..470d61b55d53 100644 --- a/src/ngLocale/angular-locale_es-ea.js +++ b/src/ngLocale/angular-locale_es-ea.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "anno D\u00f3mini" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-ec.js b/src/ngLocale/angular-locale_es-ec.js index b147de8f8602..b23330c9411c 100644 --- a/src/ngLocale/angular-locale_es-ec.js +++ b/src/ngLocale/angular-locale_es-ec.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-es.js b/src/ngLocale/angular-locale_es-es.js index 7ebe5df34b7c..971c98327e1d 100644 --- a/src/ngLocale/angular-locale_es-es.js +++ b/src/ngLocale/angular-locale_es-es.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "anno D\u00f3mini" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-gq.js b/src/ngLocale/angular-locale_es-gq.js index d0702e6c3fd3..7103281a9802 100644 --- a/src/ngLocale/angular-locale_es-gq.js +++ b/src/ngLocale/angular-locale_es-gq.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "anno D\u00f3mini" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-gt.js b/src/ngLocale/angular-locale_es-gt.js index 1f0e20e2302b..92488988ef5d 100644 --- a/src/ngLocale/angular-locale_es-gt.js +++ b/src/ngLocale/angular-locale_es-gt.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-hn.js b/src/ngLocale/angular-locale_es-hn.js index c5016170eb32..34f4369acacd 100644 --- a/src/ngLocale/angular-locale_es-hn.js +++ b/src/ngLocale/angular-locale_es-hn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-ic.js b/src/ngLocale/angular-locale_es-ic.js index c6e833fcff47..5dc87e8e1475 100644 --- a/src/ngLocale/angular-locale_es-ic.js +++ b/src/ngLocale/angular-locale_es-ic.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "anno D\u00f3mini" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-mx.js b/src/ngLocale/angular-locale_es-mx.js index 243f0cae0b8a..46c67dd3331e 100644 --- a/src/ngLocale/angular-locale_es-mx.js +++ b/src/ngLocale/angular-locale_es-mx.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "Anno Domini" + ], + "ERAS": [ + "a.C.", + "d.C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-ni.js b/src/ngLocale/angular-locale_es-ni.js index 75ad042908b7..271e846332d1 100644 --- a/src/ngLocale/angular-locale_es-ni.js +++ b/src/ngLocale/angular-locale_es-ni.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-pa.js b/src/ngLocale/angular-locale_es-pa.js index 06ad08539bab..91e7c924e530 100644 --- a/src/ngLocale/angular-locale_es-pa.js +++ b/src/ngLocale/angular-locale_es-pa.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-pe.js b/src/ngLocale/angular-locale_es-pe.js index 3bff81e1f301..798497c52a66 100644 --- a/src/ngLocale/angular-locale_es-pe.js +++ b/src/ngLocale/angular-locale_es-pe.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-ph.js b/src/ngLocale/angular-locale_es-ph.js index 0095769c1681..dded061a9a87 100644 --- a/src/ngLocale/angular-locale_es-ph.js +++ b/src/ngLocale/angular-locale_es-ph.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "anno D\u00f3mini" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-pr.js b/src/ngLocale/angular-locale_es-pr.js index 74c5ea298083..1602a5641c98 100644 --- a/src/ngLocale/angular-locale_es-pr.js +++ b/src/ngLocale/angular-locale_es-pr.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-py.js b/src/ngLocale/angular-locale_es-py.js index 6ef53e5630ff..1a8c3459fddb 100644 --- a/src/ngLocale/angular-locale_es-py.js +++ b/src/ngLocale/angular-locale_es-py.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-sv.js b/src/ngLocale/angular-locale_es-sv.js index 93ff0b44d79b..f7571741fb04 100644 --- a/src/ngLocale/angular-locale_es-sv.js +++ b/src/ngLocale/angular-locale_es-sv.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-us.js b/src/ngLocale/angular-locale_es-us.js index 8011bb5ac3d7..9baf446f6859 100644 --- a/src/ngLocale/angular-locale_es-us.js +++ b/src/ngLocale/angular-locale_es-us.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-uy.js b/src/ngLocale/angular-locale_es-uy.js index a5e62cf105c8..e43bec39c24e 100644 --- a/src/ngLocale/angular-locale_es-uy.js +++ b/src/ngLocale/angular-locale_es-uy.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es-ve.js b/src/ngLocale/angular-locale_es-ve.js index 357db87f435e..2496559d41aa 100644 --- a/src/ngLocale/angular-locale_es-ve.js +++ b/src/ngLocale/angular-locale_es-ve.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despu\u00e9s de Cristo" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_es.js b/src/ngLocale/angular-locale_es.js index c9d6c6bb7266..0a2988431120 100644 --- a/src/ngLocale/angular-locale_es.js +++ b/src/ngLocale/angular-locale_es.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "viernes", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "anno D\u00f3mini" + ], + "ERAS": [ + "a. C.", + "d. C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "enero", diff --git a/src/ngLocale/angular-locale_et-ee.js b/src/ngLocale/angular-locale_et-ee.js index 2695052f2687..3b900ae31a3d 100644 --- a/src/ngLocale/angular-locale_et-ee.js +++ b/src/ngLocale/angular-locale_et-ee.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "reede", "laup\u00e4ev" ], + "ERANAMES": [ + "enne meie aega", + "meie aja j\u00e4rgi" + ], + "ERAS": [ + "e.m.a.", + "m.a.j." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "jaanuar", diff --git a/src/ngLocale/angular-locale_et.js b/src/ngLocale/angular-locale_et.js index 396b28342e96..d10ad68a2f39 100644 --- a/src/ngLocale/angular-locale_et.js +++ b/src/ngLocale/angular-locale_et.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "reede", "laup\u00e4ev" ], + "ERANAMES": [ + "enne meie aega", + "meie aja j\u00e4rgi" + ], + "ERAS": [ + "e.m.a.", + "m.a.j." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "jaanuar", diff --git a/src/ngLocale/angular-locale_eu-es.js b/src/ngLocale/angular-locale_eu-es.js index 23ec368877e9..3a38161c4f86 100644 --- a/src/ngLocale/angular-locale_eu-es.js +++ b/src/ngLocale/angular-locale_eu-es.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "ostirala", "larunbata" ], + "ERANAMES": [ + "K.a.", + "K.o." + ], + "ERAS": [ + "K.a.", + "K.o." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "urtarrilak", diff --git a/src/ngLocale/angular-locale_eu.js b/src/ngLocale/angular-locale_eu.js index c5f9f0d48cbc..47e847112c48 100644 --- a/src/ngLocale/angular-locale_eu.js +++ b/src/ngLocale/angular-locale_eu.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "ostirala", "larunbata" ], + "ERANAMES": [ + "K.a.", + "K.o." + ], + "ERAS": [ + "K.a.", + "K.o." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "urtarrilak", diff --git a/src/ngLocale/angular-locale_ewo-cm.js b/src/ngLocale/angular-locale_ewo-cm.js index 3675fc2d9d2a..0acddea869f0 100644 --- a/src/ngLocale/angular-locale_ewo-cm.js +++ b/src/ngLocale/angular-locale_ewo-cm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "f\u00falad\u00e9", "s\u00e9rad\u00e9" ], + "ERANAMES": [ + "os\u00fas\u00faa Y\u00e9sus kiri", + "\u00e1mvus Y\u00e9sus Kir\u00eds" + ], + "ERAS": [ + "oyk", + "ayk" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "ng\u0254n os\u00fa", diff --git a/src/ngLocale/angular-locale_ewo.js b/src/ngLocale/angular-locale_ewo.js index ca5fa21d4ea1..dbef8cdecfdc 100644 --- a/src/ngLocale/angular-locale_ewo.js +++ b/src/ngLocale/angular-locale_ewo.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "f\u00falad\u00e9", "s\u00e9rad\u00e9" ], + "ERANAMES": [ + "os\u00fas\u00faa Y\u00e9sus kiri", + "\u00e1mvus Y\u00e9sus Kir\u00eds" + ], + "ERAS": [ + "oyk", + "ayk" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "ng\u0254n os\u00fa", diff --git a/src/ngLocale/angular-locale_fa-af.js b/src/ngLocale/angular-locale_fa-af.js index 4e0f9a33a2c3..cc3b6989280f 100644 --- a/src/ngLocale/angular-locale_fa-af.js +++ b/src/ngLocale/angular-locale_fa-af.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u062c\u0645\u0639\u0647", "\u0634\u0646\u0628\u0647" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0632 \u0645\u06cc\u0644\u0627\u062f", + "\u0645\u06cc\u0644\u0627\u062f\u06cc" + ], + "ERAS": [ + "\u0642.\u0645.", + "\u0645." + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u062c\u0646\u0648\u0631\u06cc", diff --git a/src/ngLocale/angular-locale_fa-ir.js b/src/ngLocale/angular-locale_fa-ir.js index ca397954b2d3..e367073e604c 100644 --- a/src/ngLocale/angular-locale_fa-ir.js +++ b/src/ngLocale/angular-locale_fa-ir.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u062c\u0645\u0639\u0647", "\u0634\u0646\u0628\u0647" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0632 \u0645\u06cc\u0644\u0627\u062f", + "\u0645\u06cc\u0644\u0627\u062f\u06cc" + ], + "ERAS": [ + "\u0642.\u0645.", + "\u0645." + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u0698\u0627\u0646\u0648\u06cc\u0647\u0654", diff --git a/src/ngLocale/angular-locale_fa.js b/src/ngLocale/angular-locale_fa.js index d8b382c4d57c..ea67fd16bc26 100644 --- a/src/ngLocale/angular-locale_fa.js +++ b/src/ngLocale/angular-locale_fa.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u062c\u0645\u0639\u0647", "\u0634\u0646\u0628\u0647" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0627\u0632 \u0645\u06cc\u0644\u0627\u062f", + "\u0645\u06cc\u0644\u0627\u062f\u06cc" + ], + "ERAS": [ + "\u0642.\u0645.", + "\u0645." + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u0698\u0627\u0646\u0648\u06cc\u0647\u0654", diff --git a/src/ngLocale/angular-locale_ff-cm.js b/src/ngLocale/angular-locale_ff-cm.js index faf5487bfcef..87589cf17524 100644 --- a/src/ngLocale/angular-locale_ff-cm.js +++ b/src/ngLocale/angular-locale_ff-cm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "mawnde", "hoore-biir" ], + "ERANAMES": [ + "Hade Iisa", + "Caggal Iisa" + ], + "ERAS": [ + "H-I", + "C-I" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "siilo", diff --git a/src/ngLocale/angular-locale_ff-gn.js b/src/ngLocale/angular-locale_ff-gn.js index 4e1da255d2d5..a7678f02d38d 100644 --- a/src/ngLocale/angular-locale_ff-gn.js +++ b/src/ngLocale/angular-locale_ff-gn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "mawnde", "hoore-biir" ], + "ERANAMES": [ + "Hade Iisa", + "Caggal Iisa" + ], + "ERAS": [ + "H-I", + "C-I" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "siilo", diff --git a/src/ngLocale/angular-locale_ff-mr.js b/src/ngLocale/angular-locale_ff-mr.js index 1331026fccfc..c36b8a2515eb 100644 --- a/src/ngLocale/angular-locale_ff-mr.js +++ b/src/ngLocale/angular-locale_ff-mr.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "mawnde", "hoore-biir" ], + "ERANAMES": [ + "Hade Iisa", + "Caggal Iisa" + ], + "ERAS": [ + "H-I", + "C-I" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "siilo", diff --git a/src/ngLocale/angular-locale_ff-sn.js b/src/ngLocale/angular-locale_ff-sn.js index 052b6b2b0f9c..e71e7b62214b 100644 --- a/src/ngLocale/angular-locale_ff-sn.js +++ b/src/ngLocale/angular-locale_ff-sn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "mawnde", "hoore-biir" ], + "ERANAMES": [ + "Hade Iisa", + "Caggal Iisa" + ], + "ERAS": [ + "H-I", + "C-I" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "siilo", diff --git a/src/ngLocale/angular-locale_ff.js b/src/ngLocale/angular-locale_ff.js index be99ee68923e..9ce7b830c6f6 100644 --- a/src/ngLocale/angular-locale_ff.js +++ b/src/ngLocale/angular-locale_ff.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "mawnde", "hoore-biir" ], + "ERANAMES": [ + "Hade Iisa", + "Caggal Iisa" + ], + "ERAS": [ + "H-I", + "C-I" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "siilo", diff --git a/src/ngLocale/angular-locale_fi-fi.js b/src/ngLocale/angular-locale_fi-fi.js index bf3d7560a38f..44bd41203986 100644 --- a/src/ngLocale/angular-locale_fi-fi.js +++ b/src/ngLocale/angular-locale_fi-fi.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "perjantaina", "lauantaina" ], + "ERANAMES": [ + "ennen Kristuksen syntym\u00e4\u00e4", + "j\u00e4lkeen Kristuksen syntym\u00e4n" + ], + "ERAS": [ + "eKr.", + "jKr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "tammikuuta", diff --git a/src/ngLocale/angular-locale_fi.js b/src/ngLocale/angular-locale_fi.js index b8e0939f6f7f..ade165642af4 100644 --- a/src/ngLocale/angular-locale_fi.js +++ b/src/ngLocale/angular-locale_fi.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "perjantaina", "lauantaina" ], + "ERANAMES": [ + "ennen Kristuksen syntym\u00e4\u00e4", + "j\u00e4lkeen Kristuksen syntym\u00e4n" + ], + "ERAS": [ + "eKr.", + "jKr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "tammikuuta", diff --git a/src/ngLocale/angular-locale_fil-ph.js b/src/ngLocale/angular-locale_fil-ph.js index c8d20f9e0e76..542243454243 100644 --- a/src/ngLocale/angular-locale_fil-ph.js +++ b/src/ngLocale/angular-locale_fil-ph.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Biyernes", "Sabado" ], + "ERANAMES": [ + "BC", + "AD" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Enero", diff --git a/src/ngLocale/angular-locale_fil.js b/src/ngLocale/angular-locale_fil.js index 89bbc63fbade..d55a9068eb17 100644 --- a/src/ngLocale/angular-locale_fil.js +++ b/src/ngLocale/angular-locale_fil.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Biyernes", "Sabado" ], + "ERANAMES": [ + "BC", + "AD" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Enero", diff --git a/src/ngLocale/angular-locale_fo-fo.js b/src/ngLocale/angular-locale_fo-fo.js index b79649fde374..a861d8c3bda9 100644 --- a/src/ngLocale/angular-locale_fo-fo.js +++ b/src/ngLocale/angular-locale_fo-fo.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "fr\u00edggjadagur", "leygardagur" ], + "ERANAMES": [ + "fyrir Krist", + "eftir Krist" + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_fo.js b/src/ngLocale/angular-locale_fo.js index f1592747a193..aa33cd323107 100644 --- a/src/ngLocale/angular-locale_fo.js +++ b/src/ngLocale/angular-locale_fo.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "fr\u00edggjadagur", "leygardagur" ], + "ERANAMES": [ + "fyrir Krist", + "eftir Krist" + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_fr-be.js b/src/ngLocale/angular-locale_fr-be.js index de2ae786da24..acec9a42545c 100644 --- a/src/ngLocale/angular-locale_fr-be.js +++ b/src/ngLocale/angular-locale_fr-be.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-bf.js b/src/ngLocale/angular-locale_fr-bf.js index f6d9d97072c5..bd30d5500301 100644 --- a/src/ngLocale/angular-locale_fr-bf.js +++ b/src/ngLocale/angular-locale_fr-bf.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-bi.js b/src/ngLocale/angular-locale_fr-bi.js index 76cb224bace4..39d3b329b628 100644 --- a/src/ngLocale/angular-locale_fr-bi.js +++ b/src/ngLocale/angular-locale_fr-bi.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-bj.js b/src/ngLocale/angular-locale_fr-bj.js index 158a92509f85..6753f0203fde 100644 --- a/src/ngLocale/angular-locale_fr-bj.js +++ b/src/ngLocale/angular-locale_fr-bj.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-bl.js b/src/ngLocale/angular-locale_fr-bl.js index f7f4df706d9b..2f15f5a32409 100644 --- a/src/ngLocale/angular-locale_fr-bl.js +++ b/src/ngLocale/angular-locale_fr-bl.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-ca.js b/src/ngLocale/angular-locale_fr-ca.js index 45da6866bc64..7056e67927e1 100644 --- a/src/ngLocale/angular-locale_fr-ca.js +++ b/src/ngLocale/angular-locale_fr-ca.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-cd.js b/src/ngLocale/angular-locale_fr-cd.js index 5f7da1887445..1e1d1cc3dc89 100644 --- a/src/ngLocale/angular-locale_fr-cd.js +++ b/src/ngLocale/angular-locale_fr-cd.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-cf.js b/src/ngLocale/angular-locale_fr-cf.js index dfa6a2e7b217..bf60553820ae 100644 --- a/src/ngLocale/angular-locale_fr-cf.js +++ b/src/ngLocale/angular-locale_fr-cf.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-cg.js b/src/ngLocale/angular-locale_fr-cg.js index b5cf0c0e3a5c..c4417732b979 100644 --- a/src/ngLocale/angular-locale_fr-cg.js +++ b/src/ngLocale/angular-locale_fr-cg.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-ch.js b/src/ngLocale/angular-locale_fr-ch.js index e9ac1f62e5bc..e69d2fe3c8fc 100644 --- a/src/ngLocale/angular-locale_fr-ch.js +++ b/src/ngLocale/angular-locale_fr-ch.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-ci.js b/src/ngLocale/angular-locale_fr-ci.js index 23c3574bedf5..2954b10386ee 100644 --- a/src/ngLocale/angular-locale_fr-ci.js +++ b/src/ngLocale/angular-locale_fr-ci.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-cm.js b/src/ngLocale/angular-locale_fr-cm.js index e10c230a42df..d8f03d2e0042 100644 --- a/src/ngLocale/angular-locale_fr-cm.js +++ b/src/ngLocale/angular-locale_fr-cm.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-dj.js b/src/ngLocale/angular-locale_fr-dj.js index 151da72ea45c..9c850c2989eb 100644 --- a/src/ngLocale/angular-locale_fr-dj.js +++ b/src/ngLocale/angular-locale_fr-dj.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-dz.js b/src/ngLocale/angular-locale_fr-dz.js index 45fb467951d2..ae1e1c67525e 100644 --- a/src/ngLocale/angular-locale_fr-dz.js +++ b/src/ngLocale/angular-locale_fr-dz.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-fr.js b/src/ngLocale/angular-locale_fr-fr.js index 2950f3bc6607..bdef4eff377e 100644 --- a/src/ngLocale/angular-locale_fr-fr.js +++ b/src/ngLocale/angular-locale_fr-fr.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-ga.js b/src/ngLocale/angular-locale_fr-ga.js index 6724a356956b..6268c7775ef2 100644 --- a/src/ngLocale/angular-locale_fr-ga.js +++ b/src/ngLocale/angular-locale_fr-ga.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-gf.js b/src/ngLocale/angular-locale_fr-gf.js index cb694f7bad18..a7d37a0ff71c 100644 --- a/src/ngLocale/angular-locale_fr-gf.js +++ b/src/ngLocale/angular-locale_fr-gf.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-gn.js b/src/ngLocale/angular-locale_fr-gn.js index 4d92cc50aa9c..34f4b1010be9 100644 --- a/src/ngLocale/angular-locale_fr-gn.js +++ b/src/ngLocale/angular-locale_fr-gn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-gp.js b/src/ngLocale/angular-locale_fr-gp.js index 8bddf476d586..9db67089d86c 100644 --- a/src/ngLocale/angular-locale_fr-gp.js +++ b/src/ngLocale/angular-locale_fr-gp.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-gq.js b/src/ngLocale/angular-locale_fr-gq.js index 7bb9b03f2b05..02bbba29455c 100644 --- a/src/ngLocale/angular-locale_fr-gq.js +++ b/src/ngLocale/angular-locale_fr-gq.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-ht.js b/src/ngLocale/angular-locale_fr-ht.js index 2182d367743b..116e0da63770 100644 --- a/src/ngLocale/angular-locale_fr-ht.js +++ b/src/ngLocale/angular-locale_fr-ht.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-km.js b/src/ngLocale/angular-locale_fr-km.js index e6a4bfe1dad1..e178c7f3d9c0 100644 --- a/src/ngLocale/angular-locale_fr-km.js +++ b/src/ngLocale/angular-locale_fr-km.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-lu.js b/src/ngLocale/angular-locale_fr-lu.js index fddc4694db65..bb2362772dc3 100644 --- a/src/ngLocale/angular-locale_fr-lu.js +++ b/src/ngLocale/angular-locale_fr-lu.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-ma.js b/src/ngLocale/angular-locale_fr-ma.js index c4860067c5ce..92edf74b5f28 100644 --- a/src/ngLocale/angular-locale_fr-ma.js +++ b/src/ngLocale/angular-locale_fr-ma.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-mc.js b/src/ngLocale/angular-locale_fr-mc.js index 7ca8ed665102..85e0233e9bba 100644 --- a/src/ngLocale/angular-locale_fr-mc.js +++ b/src/ngLocale/angular-locale_fr-mc.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-mf.js b/src/ngLocale/angular-locale_fr-mf.js index 873321e6259a..2abced5c24d4 100644 --- a/src/ngLocale/angular-locale_fr-mf.js +++ b/src/ngLocale/angular-locale_fr-mf.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-mg.js b/src/ngLocale/angular-locale_fr-mg.js index 1ab675f1d1d8..02d274787243 100644 --- a/src/ngLocale/angular-locale_fr-mg.js +++ b/src/ngLocale/angular-locale_fr-mg.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-ml.js b/src/ngLocale/angular-locale_fr-ml.js index 7d2eeea0d787..e4549e2b0d8c 100644 --- a/src/ngLocale/angular-locale_fr-ml.js +++ b/src/ngLocale/angular-locale_fr-ml.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-mq.js b/src/ngLocale/angular-locale_fr-mq.js index ce4cd9429705..3973b32e3a5c 100644 --- a/src/ngLocale/angular-locale_fr-mq.js +++ b/src/ngLocale/angular-locale_fr-mq.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-mr.js b/src/ngLocale/angular-locale_fr-mr.js index 621505c070d8..5b993c6dcfcf 100644 --- a/src/ngLocale/angular-locale_fr-mr.js +++ b/src/ngLocale/angular-locale_fr-mr.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-mu.js b/src/ngLocale/angular-locale_fr-mu.js index 6fd86dd29bb5..7b09bd2ead01 100644 --- a/src/ngLocale/angular-locale_fr-mu.js +++ b/src/ngLocale/angular-locale_fr-mu.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-nc.js b/src/ngLocale/angular-locale_fr-nc.js index d9f060c53065..a0694a9fd723 100644 --- a/src/ngLocale/angular-locale_fr-nc.js +++ b/src/ngLocale/angular-locale_fr-nc.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-ne.js b/src/ngLocale/angular-locale_fr-ne.js index d72da1095fc6..7fd048212323 100644 --- a/src/ngLocale/angular-locale_fr-ne.js +++ b/src/ngLocale/angular-locale_fr-ne.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-pf.js b/src/ngLocale/angular-locale_fr-pf.js index d0d37ae5ecd2..d5d023a330f0 100644 --- a/src/ngLocale/angular-locale_fr-pf.js +++ b/src/ngLocale/angular-locale_fr-pf.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-pm.js b/src/ngLocale/angular-locale_fr-pm.js index 86c138cd2b38..2ed15ec99554 100644 --- a/src/ngLocale/angular-locale_fr-pm.js +++ b/src/ngLocale/angular-locale_fr-pm.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-re.js b/src/ngLocale/angular-locale_fr-re.js index 920d8fd60dca..1c1e849ea7d9 100644 --- a/src/ngLocale/angular-locale_fr-re.js +++ b/src/ngLocale/angular-locale_fr-re.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-rw.js b/src/ngLocale/angular-locale_fr-rw.js index 5711f189bc2c..8966b7a8ce83 100644 --- a/src/ngLocale/angular-locale_fr-rw.js +++ b/src/ngLocale/angular-locale_fr-rw.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-sc.js b/src/ngLocale/angular-locale_fr-sc.js index 90ab555afd26..80410913af43 100644 --- a/src/ngLocale/angular-locale_fr-sc.js +++ b/src/ngLocale/angular-locale_fr-sc.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-sn.js b/src/ngLocale/angular-locale_fr-sn.js index deced1b7d338..100a1025a466 100644 --- a/src/ngLocale/angular-locale_fr-sn.js +++ b/src/ngLocale/angular-locale_fr-sn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-sy.js b/src/ngLocale/angular-locale_fr-sy.js index 93955dc911bd..8bcfaf1a1751 100644 --- a/src/ngLocale/angular-locale_fr-sy.js +++ b/src/ngLocale/angular-locale_fr-sy.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-td.js b/src/ngLocale/angular-locale_fr-td.js index 00a59db9ab27..2341ef760a1f 100644 --- a/src/ngLocale/angular-locale_fr-td.js +++ b/src/ngLocale/angular-locale_fr-td.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-tg.js b/src/ngLocale/angular-locale_fr-tg.js index eaec2cfa8797..a7c21313171d 100644 --- a/src/ngLocale/angular-locale_fr-tg.js +++ b/src/ngLocale/angular-locale_fr-tg.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-tn.js b/src/ngLocale/angular-locale_fr-tn.js index 8b0edd6618a9..14a31151a3cf 100644 --- a/src/ngLocale/angular-locale_fr-tn.js +++ b/src/ngLocale/angular-locale_fr-tn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-vu.js b/src/ngLocale/angular-locale_fr-vu.js index 37b9a1c404d8..d23d528c6c27 100644 --- a/src/ngLocale/angular-locale_fr-vu.js +++ b/src/ngLocale/angular-locale_fr-vu.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-wf.js b/src/ngLocale/angular-locale_fr-wf.js index ffa806f2d82c..bf5a357bbb9d 100644 --- a/src/ngLocale/angular-locale_fr-wf.js +++ b/src/ngLocale/angular-locale_fr-wf.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr-yt.js b/src/ngLocale/angular-locale_fr-yt.js index 628d9da8b3d4..265a0324f30d 100644 --- a/src/ngLocale/angular-locale_fr-yt.js +++ b/src/ngLocale/angular-locale_fr-yt.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fr.js b/src/ngLocale/angular-locale_fr.js index 55db43431a34..f4d89ba2a502 100644 --- a/src/ngLocale/angular-locale_fr.js +++ b/src/ngLocale/angular-locale_fr.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "vendredi", "samedi" ], + "ERANAMES": [ + "avant J\u00e9sus-Christ", + "apr\u00e8s J\u00e9sus-Christ" + ], + "ERAS": [ + "av. J.-C.", + "ap. J.-C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janvier", diff --git a/src/ngLocale/angular-locale_fur-it.js b/src/ngLocale/angular-locale_fur-it.js index 965dfec54137..ae1bf52986ae 100644 --- a/src/ngLocale/angular-locale_fur-it.js +++ b/src/ngLocale/angular-locale_fur-it.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vinars", "sabide" ], + "ERANAMES": [ + "pdC", + "ddC" + ], + "ERAS": [ + "pdC", + "ddC" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Zen\u00e2r", diff --git a/src/ngLocale/angular-locale_fur.js b/src/ngLocale/angular-locale_fur.js index 637a34d20669..3b5825bd1043 100644 --- a/src/ngLocale/angular-locale_fur.js +++ b/src/ngLocale/angular-locale_fur.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vinars", "sabide" ], + "ERANAMES": [ + "pdC", + "ddC" + ], + "ERAS": [ + "pdC", + "ddC" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Zen\u00e2r", diff --git a/src/ngLocale/angular-locale_fy-nl.js b/src/ngLocale/angular-locale_fy-nl.js index 82c480ab419d..234e983b78f2 100644 --- a/src/ngLocale/angular-locale_fy-nl.js +++ b/src/ngLocale/angular-locale_fy-nl.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "freed", "sneon" ], + "ERANAMES": [ + "Foar Kristus", + "nei Kristus" + ], + "ERAS": [ + "f.Kr.", + "n.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "jannewaris", diff --git a/src/ngLocale/angular-locale_fy.js b/src/ngLocale/angular-locale_fy.js index 681a80ac936f..6bf7ba6b0a7b 100644 --- a/src/ngLocale/angular-locale_fy.js +++ b/src/ngLocale/angular-locale_fy.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "freed", "sneon" ], + "ERANAMES": [ + "Foar Kristus", + "nei Kristus" + ], + "ERAS": [ + "f.Kr.", + "n.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "jannewaris", diff --git a/src/ngLocale/angular-locale_ga-ie.js b/src/ngLocale/angular-locale_ga-ie.js index 6d7f595d9eef..bae31a6f2306 100644 --- a/src/ngLocale/angular-locale_ga-ie.js +++ b/src/ngLocale/angular-locale_ga-ie.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "D\u00e9 hAoine", "D\u00e9 Sathairn" ], + "ERANAMES": [ + "Roimh Chr\u00edost", + "Anno Domini" + ], + "ERAS": [ + "RC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Ean\u00e1ir", diff --git a/src/ngLocale/angular-locale_ga.js b/src/ngLocale/angular-locale_ga.js index ff9143341901..e72dfdfd6300 100644 --- a/src/ngLocale/angular-locale_ga.js +++ b/src/ngLocale/angular-locale_ga.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "D\u00e9 hAoine", "D\u00e9 Sathairn" ], + "ERANAMES": [ + "Roimh Chr\u00edost", + "Anno Domini" + ], + "ERAS": [ + "RC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Ean\u00e1ir", diff --git a/src/ngLocale/angular-locale_gd-gb.js b/src/ngLocale/angular-locale_gd-gb.js index 1e679dfa60b2..d38c9483c1f3 100644 --- a/src/ngLocale/angular-locale_gd-gb.js +++ b/src/ngLocale/angular-locale_gd-gb.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "DihAoine", "DiSathairne" ], + "ERANAMES": [ + "Ro Chr\u00ecosta", + "An d\u00e8idh Chr\u00ecosta" + ], + "ERAS": [ + "RC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "dhen Fhaoilleach", diff --git a/src/ngLocale/angular-locale_gd.js b/src/ngLocale/angular-locale_gd.js index 5d2577274b04..4821cc50b2d1 100644 --- a/src/ngLocale/angular-locale_gd.js +++ b/src/ngLocale/angular-locale_gd.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "DihAoine", "DiSathairne" ], + "ERANAMES": [ + "Ro Chr\u00ecosta", + "An d\u00e8idh Chr\u00ecosta" + ], + "ERAS": [ + "RC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "dhen Fhaoilleach", diff --git a/src/ngLocale/angular-locale_gl-es.js b/src/ngLocale/angular-locale_gl-es.js index 519f9785edff..c5777ee6a4b1 100644 --- a/src/ngLocale/angular-locale_gl-es.js +++ b/src/ngLocale/angular-locale_gl-es.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "venres", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despois de Cristo" + ], + "ERAS": [ + "a.C.", + "d.C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "xaneiro", diff --git a/src/ngLocale/angular-locale_gl.js b/src/ngLocale/angular-locale_gl.js index b080328d02fd..f0e101efe884 100644 --- a/src/ngLocale/angular-locale_gl.js +++ b/src/ngLocale/angular-locale_gl.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "venres", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "despois de Cristo" + ], + "ERAS": [ + "a.C.", + "d.C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "xaneiro", diff --git a/src/ngLocale/angular-locale_gsw-ch.js b/src/ngLocale/angular-locale_gsw-ch.js index fed3bc0e50bf..54278de0ac70 100644 --- a/src/ngLocale/angular-locale_gsw-ch.js +++ b/src/ngLocale/angular-locale_gsw-ch.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Friitig", "Samschtig" ], + "ERANAMES": [ + "v. Chr.", + "n. Chr." + ], + "ERAS": [ + "v. Chr.", + "n. Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januar", diff --git a/src/ngLocale/angular-locale_gsw-fr.js b/src/ngLocale/angular-locale_gsw-fr.js index 0800cdbbb99f..979ced7a77e4 100644 --- a/src/ngLocale/angular-locale_gsw-fr.js +++ b/src/ngLocale/angular-locale_gsw-fr.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Friitig", "Samschtig" ], + "ERANAMES": [ + "v. Chr.", + "n. Chr." + ], + "ERAS": [ + "v. Chr.", + "n. Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januar", diff --git a/src/ngLocale/angular-locale_gsw-li.js b/src/ngLocale/angular-locale_gsw-li.js index b1d8b48e0c1a..c1a5aebcfb76 100644 --- a/src/ngLocale/angular-locale_gsw-li.js +++ b/src/ngLocale/angular-locale_gsw-li.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Friitig", "Samschtig" ], + "ERANAMES": [ + "v. Chr.", + "n. Chr." + ], + "ERAS": [ + "v. Chr.", + "n. Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januar", diff --git a/src/ngLocale/angular-locale_gsw.js b/src/ngLocale/angular-locale_gsw.js index 8f8187caf6fa..93ef2cd09ac0 100644 --- a/src/ngLocale/angular-locale_gsw.js +++ b/src/ngLocale/angular-locale_gsw.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Friitig", "Samschtig" ], + "ERANAMES": [ + "v. Chr.", + "n. Chr." + ], + "ERAS": [ + "v. Chr.", + "n. Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januar", diff --git a/src/ngLocale/angular-locale_gu-in.js b/src/ngLocale/angular-locale_gu-in.js index 66270537f0f5..ffceb35d2e7a 100644 --- a/src/ngLocale/angular-locale_gu-in.js +++ b/src/ngLocale/angular-locale_gu-in.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0ab6\u0ac1\u0a95\u0acd\u0ab0\u0ab5\u0abe\u0ab0", "\u0ab6\u0aa8\u0abf\u0ab5\u0abe\u0ab0" ], + "ERANAMES": [ + "\u0a88\u0ab8\u0ab5\u0ac0\u0ab8\u0aa8 \u0aaa\u0ac2\u0ab0\u0acd\u0ab5\u0ac7", + "\u0a87\u0ab8\u0ab5\u0ac0\u0ab8\u0aa8" + ], + "ERAS": [ + "\u0a88\u0ab8\u0ac1\u0aa8\u0abe \u0a9c\u0aa8\u0acd\u0aae \u0aaa\u0ab9\u0ac7\u0ab2\u0abe", + "\u0a87\u0ab8\u0ab5\u0ac0\u0ab8\u0aa8" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0a9c\u0abe\u0aa8\u0acd\u0aaf\u0ac1\u0a86\u0ab0\u0ac0", diff --git a/src/ngLocale/angular-locale_gu.js b/src/ngLocale/angular-locale_gu.js index 63fe4bd0eeb0..660fcf87882b 100644 --- a/src/ngLocale/angular-locale_gu.js +++ b/src/ngLocale/angular-locale_gu.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0ab6\u0ac1\u0a95\u0acd\u0ab0\u0ab5\u0abe\u0ab0", "\u0ab6\u0aa8\u0abf\u0ab5\u0abe\u0ab0" ], + "ERANAMES": [ + "\u0a88\u0ab8\u0ab5\u0ac0\u0ab8\u0aa8 \u0aaa\u0ac2\u0ab0\u0acd\u0ab5\u0ac7", + "\u0a87\u0ab8\u0ab5\u0ac0\u0ab8\u0aa8" + ], + "ERAS": [ + "\u0a88\u0ab8\u0ac1\u0aa8\u0abe \u0a9c\u0aa8\u0acd\u0aae \u0aaa\u0ab9\u0ac7\u0ab2\u0abe", + "\u0a87\u0ab8\u0ab5\u0ac0\u0ab8\u0aa8" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0a9c\u0abe\u0aa8\u0acd\u0aaf\u0ac1\u0a86\u0ab0\u0ac0", diff --git a/src/ngLocale/angular-locale_guz-ke.js b/src/ngLocale/angular-locale_guz-ke.js index ed1d8658b1aa..d2f9497a493e 100644 --- a/src/ngLocale/angular-locale_guz-ke.js +++ b/src/ngLocale/angular-locale_guz-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ichuma", "Esabato" ], + "ERANAMES": [ + "Yeso ataiborwa", + "Yeso kaiboirwe" + ], + "ERAS": [ + "YA", + "YK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Chanuari", diff --git a/src/ngLocale/angular-locale_guz.js b/src/ngLocale/angular-locale_guz.js index 618c28568490..a2c578e51da7 100644 --- a/src/ngLocale/angular-locale_guz.js +++ b/src/ngLocale/angular-locale_guz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ichuma", "Esabato" ], + "ERANAMES": [ + "Yeso ataiborwa", + "Yeso kaiboirwe" + ], + "ERAS": [ + "YA", + "YK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Chanuari", diff --git a/src/ngLocale/angular-locale_gv-im.js b/src/ngLocale/angular-locale_gv-im.js index 6a829977c5db..84e3b5e66aa0 100644 --- a/src/ngLocale/angular-locale_gv-im.js +++ b/src/ngLocale/angular-locale_gv-im.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jeheiney", "Jesarn" ], + "ERANAMES": [ + "RC", + "AD" + ], + "ERAS": [ + "RC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Jerrey-geuree", diff --git a/src/ngLocale/angular-locale_gv.js b/src/ngLocale/angular-locale_gv.js index 27a00bb47927..4b20973ee185 100644 --- a/src/ngLocale/angular-locale_gv.js +++ b/src/ngLocale/angular-locale_gv.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jeheiney", "Jesarn" ], + "ERANAMES": [ + "RC", + "AD" + ], + "ERAS": [ + "RC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Jerrey-geuree", diff --git a/src/ngLocale/angular-locale_ha-latn-gh.js b/src/ngLocale/angular-locale_ha-latn-gh.js index a088a26f4c33..cc0413041bb3 100644 --- a/src/ngLocale/angular-locale_ha-latn-gh.js +++ b/src/ngLocale/angular-locale_ha-latn-gh.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jumma\u02bca", "Asabar" ], + "ERANAMES": [ + "Kafin haihuwar annab", + "Bayan haihuwar annab" + ], + "ERAS": [ + "KHAI", + "BHAI" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Janairu", diff --git a/src/ngLocale/angular-locale_ha-latn-ne.js b/src/ngLocale/angular-locale_ha-latn-ne.js index 398ebe303748..24aa85286926 100644 --- a/src/ngLocale/angular-locale_ha-latn-ne.js +++ b/src/ngLocale/angular-locale_ha-latn-ne.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jumma\u02bca", "Asabar" ], + "ERANAMES": [ + "Kafin haihuwar annab", + "Bayan haihuwar annab" + ], + "ERAS": [ + "KHAI", + "BHAI" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Janairu", diff --git a/src/ngLocale/angular-locale_ha-latn-ng.js b/src/ngLocale/angular-locale_ha-latn-ng.js index 683131c6ae92..8bc6e43a5c9e 100644 --- a/src/ngLocale/angular-locale_ha-latn-ng.js +++ b/src/ngLocale/angular-locale_ha-latn-ng.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jumma\u02bca", "Asabar" ], + "ERANAMES": [ + "Kafin haihuwar annab", + "Bayan haihuwar annab" + ], + "ERAS": [ + "KHAI", + "BHAI" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Janairu", diff --git a/src/ngLocale/angular-locale_ha-latn.js b/src/ngLocale/angular-locale_ha-latn.js index f105fe62b053..2a39210650c8 100644 --- a/src/ngLocale/angular-locale_ha-latn.js +++ b/src/ngLocale/angular-locale_ha-latn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jumma\u02bca", "Asabar" ], + "ERANAMES": [ + "Kafin haihuwar annab", + "Bayan haihuwar annab" + ], + "ERAS": [ + "KHAI", + "BHAI" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Janairu", diff --git a/src/ngLocale/angular-locale_ha.js b/src/ngLocale/angular-locale_ha.js index 2b988cc81824..5e4f2cdcab7c 100644 --- a/src/ngLocale/angular-locale_ha.js +++ b/src/ngLocale/angular-locale_ha.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jumma\u02bca", "Asabar" ], + "ERANAMES": [ + "Kafin haihuwar annab", + "Bayan haihuwar annab" + ], + "ERAS": [ + "KHAI", + "BHAI" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Janairu", diff --git a/src/ngLocale/angular-locale_haw-us.js b/src/ngLocale/angular-locale_haw-us.js index 127b71b5c4ee..cb9388b146a2 100644 --- a/src/ngLocale/angular-locale_haw-us.js +++ b/src/ngLocale/angular-locale_haw-us.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Po\u02bbalima", "Po\u02bbaono" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Ianuali", diff --git a/src/ngLocale/angular-locale_haw.js b/src/ngLocale/angular-locale_haw.js index dbbd7ce90f7c..5479d9911a99 100644 --- a/src/ngLocale/angular-locale_haw.js +++ b/src/ngLocale/angular-locale_haw.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Po\u02bbalima", "Po\u02bbaono" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Ianuali", diff --git a/src/ngLocale/angular-locale_he-il.js b/src/ngLocale/angular-locale_he-il.js index c3e08df69d43..b6188e465651 100644 --- a/src/ngLocale/angular-locale_he-il.js +++ b/src/ngLocale/angular-locale_he-il.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u05d9\u05d5\u05dd \u05e9\u05d9\u05e9\u05d9", "\u05d9\u05d5\u05dd \u05e9\u05d1\u05ea" ], + "ERANAMES": [ + "\u05dc\u05e4\u05e0\u05d9 \u05d4\u05e1\u05e4\u05d9\u05e8\u05d4", + "\u05dc\u05e1\u05e4\u05d9\u05e8\u05d4" + ], + "ERAS": [ + "\u05dc\u05e4\u05e0\u05d4\u05f4\u05e1", + "\u05dc\u05e1\u05e4\u05d9\u05e8\u05d4" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u05d9\u05e0\u05d5\u05d0\u05e8", diff --git a/src/ngLocale/angular-locale_he.js b/src/ngLocale/angular-locale_he.js index f1ce8c18dd01..ebbae4f623cf 100644 --- a/src/ngLocale/angular-locale_he.js +++ b/src/ngLocale/angular-locale_he.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u05d9\u05d5\u05dd \u05e9\u05d9\u05e9\u05d9", "\u05d9\u05d5\u05dd \u05e9\u05d1\u05ea" ], + "ERANAMES": [ + "\u05dc\u05e4\u05e0\u05d9 \u05d4\u05e1\u05e4\u05d9\u05e8\u05d4", + "\u05dc\u05e1\u05e4\u05d9\u05e8\u05d4" + ], + "ERAS": [ + "\u05dc\u05e4\u05e0\u05d4\u05f4\u05e1", + "\u05dc\u05e1\u05e4\u05d9\u05e8\u05d4" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u05d9\u05e0\u05d5\u05d0\u05e8", diff --git a/src/ngLocale/angular-locale_hi-in.js b/src/ngLocale/angular-locale_hi-in.js index 529d5be5f8f6..1803c689c951 100644 --- a/src/ngLocale/angular-locale_hi-in.js +++ b/src/ngLocale/angular-locale_hi-in.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930", "\u0936\u0928\u093f\u0935\u093e\u0930" ], + "ERANAMES": [ + "\u0908\u0938\u093e-\u092a\u0942\u0930\u094d\u0935", + "\u0908\u0938\u0935\u0940 \u0938\u0928" + ], + "ERAS": [ + "\u0908\u0938\u093e-\u092a\u0942\u0930\u094d\u0935", + "\u0908\u0938\u094d\u0935\u0940" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u091c\u0928\u0935\u0930\u0940", diff --git a/src/ngLocale/angular-locale_hi.js b/src/ngLocale/angular-locale_hi.js index e52f05c673f9..210129d8d212 100644 --- a/src/ngLocale/angular-locale_hi.js +++ b/src/ngLocale/angular-locale_hi.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930", "\u0936\u0928\u093f\u0935\u093e\u0930" ], + "ERANAMES": [ + "\u0908\u0938\u093e-\u092a\u0942\u0930\u094d\u0935", + "\u0908\u0938\u0935\u0940 \u0938\u0928" + ], + "ERAS": [ + "\u0908\u0938\u093e-\u092a\u0942\u0930\u094d\u0935", + "\u0908\u0938\u094d\u0935\u0940" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u091c\u0928\u0935\u0930\u0940", diff --git a/src/ngLocale/angular-locale_hr-ba.js b/src/ngLocale/angular-locale_hr-ba.js index 7b78bbe238b1..cb70c76e7415 100644 --- a/src/ngLocale/angular-locale_hr-ba.js +++ b/src/ngLocale/angular-locale_hr-ba.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "petak", "subota" ], + "ERANAMES": [ + "Prije Krista", + "Poslije Krista" + ], + "ERAS": [ + "pr. Kr.", + "p. Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "sije\u010dnja", diff --git a/src/ngLocale/angular-locale_hr-hr.js b/src/ngLocale/angular-locale_hr-hr.js index b517ccb6050b..248734f6b069 100644 --- a/src/ngLocale/angular-locale_hr-hr.js +++ b/src/ngLocale/angular-locale_hr-hr.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "petak", "subota" ], + "ERANAMES": [ + "Prije Krista", + "Poslije Krista" + ], + "ERAS": [ + "pr. Kr.", + "p. Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "sije\u010dnja", diff --git a/src/ngLocale/angular-locale_hr.js b/src/ngLocale/angular-locale_hr.js index ca2b9e4d0c32..4f6f1c140cf1 100644 --- a/src/ngLocale/angular-locale_hr.js +++ b/src/ngLocale/angular-locale_hr.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "petak", "subota" ], + "ERANAMES": [ + "Prije Krista", + "Poslije Krista" + ], + "ERAS": [ + "pr. Kr.", + "p. Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "sije\u010dnja", diff --git a/src/ngLocale/angular-locale_hsb-de.js b/src/ngLocale/angular-locale_hsb-de.js index 7a7575a400d4..f432ed9491c4 100644 --- a/src/ngLocale/angular-locale_hsb-de.js +++ b/src/ngLocale/angular-locale_hsb-de.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "pjatk", "sobota" ], + "ERANAMES": [ + "p\u0159ed Chrystowym narod\u017aenjom", + "po Chrystowym narod\u017aenju" + ], + "ERAS": [ + "p\u0159.Chr.n.", + "po Chr.n." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januara", diff --git a/src/ngLocale/angular-locale_hsb.js b/src/ngLocale/angular-locale_hsb.js index 006b239483f2..c11ebc7832e9 100644 --- a/src/ngLocale/angular-locale_hsb.js +++ b/src/ngLocale/angular-locale_hsb.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "pjatk", "sobota" ], + "ERANAMES": [ + "p\u0159ed Chrystowym narod\u017aenjom", + "po Chrystowym narod\u017aenju" + ], + "ERAS": [ + "p\u0159.Chr.n.", + "po Chr.n." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januara", diff --git a/src/ngLocale/angular-locale_hu-hu.js b/src/ngLocale/angular-locale_hu-hu.js index 083f2a37cb3b..10a3bbc518fe 100644 --- a/src/ngLocale/angular-locale_hu-hu.js +++ b/src/ngLocale/angular-locale_hu-hu.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "p\u00e9ntek", "szombat" ], + "ERANAMES": [ + "id\u0151sz\u00e1m\u00edt\u00e1sunk el\u0151tt", + "id\u0151sz\u00e1m\u00edt\u00e1sunk szerint" + ], + "ERAS": [ + "i. e.", + "i. sz." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janu\u00e1r", diff --git a/src/ngLocale/angular-locale_hu.js b/src/ngLocale/angular-locale_hu.js index f8b5fc789f36..1e61f045e215 100644 --- a/src/ngLocale/angular-locale_hu.js +++ b/src/ngLocale/angular-locale_hu.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "p\u00e9ntek", "szombat" ], + "ERANAMES": [ + "id\u0151sz\u00e1m\u00edt\u00e1sunk el\u0151tt", + "id\u0151sz\u00e1m\u00edt\u00e1sunk szerint" + ], + "ERAS": [ + "i. e.", + "i. sz." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janu\u00e1r", diff --git a/src/ngLocale/angular-locale_hy-am.js b/src/ngLocale/angular-locale_hy-am.js index 96c88a728f2e..17afd2763bd9 100644 --- a/src/ngLocale/angular-locale_hy-am.js +++ b/src/ngLocale/angular-locale_hy-am.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0578\u0582\u0580\u0562\u0561\u0569", "\u0577\u0561\u0562\u0561\u0569" ], + "ERANAMES": [ + "\u0574.\u0569.\u0561.", + "\u0574.\u0569." + ], + "ERAS": [ + "\u0574.\u0569.\u0561.", + "\u0574.\u0569." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0570\u0578\u0582\u0576\u057e\u0561\u0580\u056b", diff --git a/src/ngLocale/angular-locale_hy.js b/src/ngLocale/angular-locale_hy.js index 0dc4be27c678..c54fe770fdfc 100644 --- a/src/ngLocale/angular-locale_hy.js +++ b/src/ngLocale/angular-locale_hy.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0578\u0582\u0580\u0562\u0561\u0569", "\u0577\u0561\u0562\u0561\u0569" ], + "ERANAMES": [ + "\u0574.\u0569.\u0561.", + "\u0574.\u0569." + ], + "ERAS": [ + "\u0574.\u0569.\u0561.", + "\u0574.\u0569." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0570\u0578\u0582\u0576\u057e\u0561\u0580\u056b", diff --git a/src/ngLocale/angular-locale_ia-fr.js b/src/ngLocale/angular-locale_ia-fr.js index 1aade03212ae..f7b636b34697 100644 --- a/src/ngLocale/angular-locale_ia-fr.js +++ b/src/ngLocale/angular-locale_ia-fr.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "venerdi", "sabbato" ], + "ERANAMES": [ + "ante Christo", + "post Christo" + ], + "ERAS": [ + "a.Chr.", + "p.Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januario", diff --git a/src/ngLocale/angular-locale_ia.js b/src/ngLocale/angular-locale_ia.js index 678ba54a3183..38ead226c951 100644 --- a/src/ngLocale/angular-locale_ia.js +++ b/src/ngLocale/angular-locale_ia.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "venerdi", "sabbato" ], + "ERANAMES": [ + "ante Christo", + "post Christo" + ], + "ERAS": [ + "a.Chr.", + "p.Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januario", diff --git a/src/ngLocale/angular-locale_id-id.js b/src/ngLocale/angular-locale_id-id.js index 85230b86213e..4a97f0b95749 100644 --- a/src/ngLocale/angular-locale_id-id.js +++ b/src/ngLocale/angular-locale_id-id.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Jumat", "Sabtu" ], + "ERANAMES": [ + "Sebelum Masehi", + "M" + ], + "ERAS": [ + "SM", + "M" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_id.js b/src/ngLocale/angular-locale_id.js index 04aa764970d7..0f0f02fa74ca 100644 --- a/src/ngLocale/angular-locale_id.js +++ b/src/ngLocale/angular-locale_id.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Jumat", "Sabtu" ], + "ERANAMES": [ + "Sebelum Masehi", + "M" + ], + "ERAS": [ + "SM", + "M" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_ig-ng.js b/src/ngLocale/angular-locale_ig-ng.js index d635a076b688..535c4a8a07d8 100644 --- a/src/ngLocale/angular-locale_ig-ng.js +++ b/src/ngLocale/angular-locale_ig-ng.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Fra\u1ecbdee", "Sat\u1ecddee" ], + "ERANAMES": [ + "Tupu Kristi", + "Af\u1ecd Kristi" + ], + "ERAS": [ + "T.K.", + "A.K." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Jen\u1ee5war\u1ecb", diff --git a/src/ngLocale/angular-locale_ig.js b/src/ngLocale/angular-locale_ig.js index ef528c316573..5de147ccfa2c 100644 --- a/src/ngLocale/angular-locale_ig.js +++ b/src/ngLocale/angular-locale_ig.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Fra\u1ecbdee", "Sat\u1ecddee" ], + "ERANAMES": [ + "Tupu Kristi", + "Af\u1ecd Kristi" + ], + "ERAS": [ + "T.K.", + "A.K." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Jen\u1ee5war\u1ecb", diff --git a/src/ngLocale/angular-locale_ii-cn.js b/src/ngLocale/angular-locale_ii-cn.js index 5a9a53fb77fe..badb33391783 100644 --- a/src/ngLocale/angular-locale_ii-cn.js +++ b/src/ngLocale/angular-locale_ii-cn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\ua18f\ua282\ua26c", "\ua18f\ua282\ua0d8" ], + "ERANAMES": [ + "\ua0c5\ua2ca\ua0bf", + "\ua0c5\ua2ca\ua282" + ], + "ERAS": [ + "\ua0c5\ua2ca\ua0bf", + "\ua0c5\ua2ca\ua282" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\ua2cd\ua1aa", diff --git a/src/ngLocale/angular-locale_ii.js b/src/ngLocale/angular-locale_ii.js index 8f226cd98475..3e3aa1a89063 100644 --- a/src/ngLocale/angular-locale_ii.js +++ b/src/ngLocale/angular-locale_ii.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\ua18f\ua282\ua26c", "\ua18f\ua282\ua0d8" ], + "ERANAMES": [ + "\ua0c5\ua2ca\ua0bf", + "\ua0c5\ua2ca\ua282" + ], + "ERAS": [ + "\ua0c5\ua2ca\ua0bf", + "\ua0c5\ua2ca\ua282" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\ua2cd\ua1aa", diff --git a/src/ngLocale/angular-locale_in.js b/src/ngLocale/angular-locale_in.js index 9f4c667f0583..80d20a8ee571 100644 --- a/src/ngLocale/angular-locale_in.js +++ b/src/ngLocale/angular-locale_in.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Jumat", "Sabtu" ], + "ERANAMES": [ + "Sebelum Masehi", + "M" + ], + "ERAS": [ + "SM", + "M" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_is-is.js b/src/ngLocale/angular-locale_is-is.js index 5a6a7b7756d2..b38bd19fe2df 100644 --- a/src/ngLocale/angular-locale_is-is.js +++ b/src/ngLocale/angular-locale_is-is.js @@ -47,6 +47,14 @@ $provide.value("$locale", { "f\u00f6studagur", "laugardagur" ], + "ERANAMES": [ + "fyrir Krist", + "eftir Krist" + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "jan\u00faar", diff --git a/src/ngLocale/angular-locale_is.js b/src/ngLocale/angular-locale_is.js index e242adc09af1..5b3ad4313a56 100644 --- a/src/ngLocale/angular-locale_is.js +++ b/src/ngLocale/angular-locale_is.js @@ -47,6 +47,14 @@ $provide.value("$locale", { "f\u00f6studagur", "laugardagur" ], + "ERANAMES": [ + "fyrir Krist", + "eftir Krist" + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "jan\u00faar", diff --git a/src/ngLocale/angular-locale_it-ch.js b/src/ngLocale/angular-locale_it-ch.js index 8b2ddbf62891..1adbbe48eeb3 100644 --- a/src/ngLocale/angular-locale_it-ch.js +++ b/src/ngLocale/angular-locale_it-ch.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "venerd\u00ec", "sabato" ], + "ERANAMES": [ + "a.C.", + "d.C." + ], + "ERAS": [ + "aC", + "dC" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "gennaio", diff --git a/src/ngLocale/angular-locale_it-it.js b/src/ngLocale/angular-locale_it-it.js index 012f93abeee8..f02cc459f1b8 100644 --- a/src/ngLocale/angular-locale_it-it.js +++ b/src/ngLocale/angular-locale_it-it.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "venerd\u00ec", "sabato" ], + "ERANAMES": [ + "a.C.", + "d.C." + ], + "ERAS": [ + "aC", + "dC" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "gennaio", diff --git a/src/ngLocale/angular-locale_it-sm.js b/src/ngLocale/angular-locale_it-sm.js index c02e0068aac5..5ee2ce18efd3 100644 --- a/src/ngLocale/angular-locale_it-sm.js +++ b/src/ngLocale/angular-locale_it-sm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "venerd\u00ec", "sabato" ], + "ERANAMES": [ + "a.C.", + "d.C." + ], + "ERAS": [ + "aC", + "dC" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "gennaio", diff --git a/src/ngLocale/angular-locale_it.js b/src/ngLocale/angular-locale_it.js index 22bd8e6f6889..b4b5e4e590e6 100644 --- a/src/ngLocale/angular-locale_it.js +++ b/src/ngLocale/angular-locale_it.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "venerd\u00ec", "sabato" ], + "ERANAMES": [ + "a.C.", + "d.C." + ], + "ERAS": [ + "aC", + "dC" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "gennaio", diff --git a/src/ngLocale/angular-locale_iw.js b/src/ngLocale/angular-locale_iw.js index 6c22c72d52d0..d890cba9d066 100644 --- a/src/ngLocale/angular-locale_iw.js +++ b/src/ngLocale/angular-locale_iw.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u05d9\u05d5\u05dd \u05e9\u05d9\u05e9\u05d9", "\u05d9\u05d5\u05dd \u05e9\u05d1\u05ea" ], + "ERANAMES": [ + "\u05dc\u05e4\u05e0\u05d9 \u05d4\u05e1\u05e4\u05d9\u05e8\u05d4", + "\u05dc\u05e1\u05e4\u05d9\u05e8\u05d4" + ], + "ERAS": [ + "\u05dc\u05e4\u05e0\u05d4\u05f4\u05e1", + "\u05dc\u05e1\u05e4\u05d9\u05e8\u05d4" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u05d9\u05e0\u05d5\u05d0\u05e8", diff --git a/src/ngLocale/angular-locale_ja-jp.js b/src/ngLocale/angular-locale_ja-jp.js index 54197ac03175..7cc214314266 100644 --- a/src/ngLocale/angular-locale_ja-jp.js +++ b/src/ngLocale/angular-locale_ja-jp.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u91d1\u66dc\u65e5", "\u571f\u66dc\u65e5" ], + "ERANAMES": [ + "\u7d00\u5143\u524d", + "\u897f\u66a6" + ], + "ERAS": [ + "\u7d00\u5143\u524d", + "\u897f\u66a6" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "1\u6708", diff --git a/src/ngLocale/angular-locale_ja.js b/src/ngLocale/angular-locale_ja.js index 61f7b748cb5a..9255172cf022 100644 --- a/src/ngLocale/angular-locale_ja.js +++ b/src/ngLocale/angular-locale_ja.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u91d1\u66dc\u65e5", "\u571f\u66dc\u65e5" ], + "ERANAMES": [ + "\u7d00\u5143\u524d", + "\u897f\u66a6" + ], + "ERAS": [ + "\u7d00\u5143\u524d", + "\u897f\u66a6" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "1\u6708", diff --git a/src/ngLocale/angular-locale_jgo-cm.js b/src/ngLocale/angular-locale_jgo-cm.js index 38e0029026ca..73f4719ac4c2 100644 --- a/src/ngLocale/angular-locale_jgo-cm.js +++ b/src/ngLocale/angular-locale_jgo-cm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "F\u025bl\u00e2y\u025bd\u025b", "S\u00e1sid\u025b" ], + "ERANAMES": [ + "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 l\u025b\u025bn\u025b K\u025bl\u00eds\u025bt\u0254 g\u0254 \u0144\u0254\u0301", + "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 f\u00fan\u025b K\u025bl\u00eds\u025bt\u0254 t\u0254\u0301 m\u0254\u0301" + ], + "ERAS": [ + "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 l\u025b\u025bn\u025b K\u025bl\u00eds\u025bt\u0254 g\u0254 \u0144\u0254\u0301", + "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 f\u00fan\u025b K\u025bl\u00eds\u025bt\u0254 t\u0254\u0301 m\u0254\u0301" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Ndu\u014bmbi Sa\u014b", diff --git a/src/ngLocale/angular-locale_jgo.js b/src/ngLocale/angular-locale_jgo.js index 515b8e783d21..11f1e841922c 100644 --- a/src/ngLocale/angular-locale_jgo.js +++ b/src/ngLocale/angular-locale_jgo.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "F\u025bl\u00e2y\u025bd\u025b", "S\u00e1sid\u025b" ], + "ERANAMES": [ + "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 l\u025b\u025bn\u025b K\u025bl\u00eds\u025bt\u0254 g\u0254 \u0144\u0254\u0301", + "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 f\u00fan\u025b K\u025bl\u00eds\u025bt\u0254 t\u0254\u0301 m\u0254\u0301" + ], + "ERAS": [ + "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 l\u025b\u025bn\u025b K\u025bl\u00eds\u025bt\u0254 g\u0254 \u0144\u0254\u0301", + "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 f\u00fan\u025b K\u025bl\u00eds\u025bt\u0254 t\u0254\u0301 m\u0254\u0301" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Ndu\u014bmbi Sa\u014b", diff --git a/src/ngLocale/angular-locale_jmc-tz.js b/src/ngLocale/angular-locale_jmc-tz.js index 7ae745e6422e..75e974b8f6e1 100644 --- a/src/ngLocale/angular-locale_jmc-tz.js +++ b/src/ngLocale/angular-locale_jmc-tz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Kabla ya Kristu", + "Baada ya Kristu" + ], + "ERAS": [ + "KK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_jmc.js b/src/ngLocale/angular-locale_jmc.js index 9195fdea7e2b..bd6df370f5d4 100644 --- a/src/ngLocale/angular-locale_jmc.js +++ b/src/ngLocale/angular-locale_jmc.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Kabla ya Kristu", + "Baada ya Kristu" + ], + "ERAS": [ + "KK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_ka-ge.js b/src/ngLocale/angular-locale_ka-ge.js index a017969fe681..4383940aa5c7 100644 --- a/src/ngLocale/angular-locale_ka-ge.js +++ b/src/ngLocale/angular-locale_ka-ge.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u10de\u10d0\u10e0\u10d0\u10e1\u10d9\u10d4\u10d5\u10d8", "\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8" ], + "ERANAMES": [ + "\u10eb\u10d5\u10d4\u10da\u10d8 \u10ec\u10d4\u10da\u10d7\u10d0\u10e6\u10e0\u10d8\u10ea\u10ee\u10d5\u10d8\u10d7", + "\u10d0\u10ee\u10d0\u10da\u10d8 \u10ec\u10d4\u10da\u10d7\u10d0\u10e6\u10e0\u10d8\u10ea\u10ee\u10d5\u10d8\u10d7" + ], + "ERAS": [ + "\u10eb\u10d5. \u10ec.", + "\u10d0\u10ee. \u10ec." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u10d8\u10d0\u10dc\u10d5\u10d0\u10e0\u10d8", diff --git a/src/ngLocale/angular-locale_ka.js b/src/ngLocale/angular-locale_ka.js index e80f6612e733..fc846caeac23 100644 --- a/src/ngLocale/angular-locale_ka.js +++ b/src/ngLocale/angular-locale_ka.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u10de\u10d0\u10e0\u10d0\u10e1\u10d9\u10d4\u10d5\u10d8", "\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8" ], + "ERANAMES": [ + "\u10eb\u10d5\u10d4\u10da\u10d8 \u10ec\u10d4\u10da\u10d7\u10d0\u10e6\u10e0\u10d8\u10ea\u10ee\u10d5\u10d8\u10d7", + "\u10d0\u10ee\u10d0\u10da\u10d8 \u10ec\u10d4\u10da\u10d7\u10d0\u10e6\u10e0\u10d8\u10ea\u10ee\u10d5\u10d8\u10d7" + ], + "ERAS": [ + "\u10eb\u10d5. \u10ec.", + "\u10d0\u10ee. \u10ec." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u10d8\u10d0\u10dc\u10d5\u10d0\u10e0\u10d8", diff --git a/src/ngLocale/angular-locale_kab-dz.js b/src/ngLocale/angular-locale_kab-dz.js index bfcd6b9925f5..6063c588f24b 100644 --- a/src/ngLocale/angular-locale_kab-dz.js +++ b/src/ngLocale/angular-locale_kab-dz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "S\u1e0disass", "Sayass" ], + "ERANAMES": [ + "send talalit n \u0190isa", + "seld talalit n \u0190isa" + ], + "ERAS": [ + "snd. T.\u0190", + "sld. T.\u0190" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Yennayer", diff --git a/src/ngLocale/angular-locale_kab.js b/src/ngLocale/angular-locale_kab.js index b8a3bbac10d0..d7b82a94e863 100644 --- a/src/ngLocale/angular-locale_kab.js +++ b/src/ngLocale/angular-locale_kab.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "S\u1e0disass", "Sayass" ], + "ERANAMES": [ + "send talalit n \u0190isa", + "seld talalit n \u0190isa" + ], + "ERAS": [ + "snd. T.\u0190", + "sld. T.\u0190" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Yennayer", diff --git a/src/ngLocale/angular-locale_kam-ke.js b/src/ngLocale/angular-locale_kam-ke.js index fea40dc0af8f..32406b765799 100644 --- a/src/ngLocale/angular-locale_kam-ke.js +++ b/src/ngLocale/angular-locale_kam-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Wa katano", "Wa thanthat\u0169" ], + "ERANAMES": [ + "Mbee wa Yes\u0169", + "\u0128tina wa Yes\u0169" + ], + "ERAS": [ + "MY", + "IY" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mwai wa mbee", diff --git a/src/ngLocale/angular-locale_kam.js b/src/ngLocale/angular-locale_kam.js index 6b6adcaa7cb6..364a1c0e2c74 100644 --- a/src/ngLocale/angular-locale_kam.js +++ b/src/ngLocale/angular-locale_kam.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Wa katano", "Wa thanthat\u0169" ], + "ERANAMES": [ + "Mbee wa Yes\u0169", + "\u0128tina wa Yes\u0169" + ], + "ERAS": [ + "MY", + "IY" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mwai wa mbee", diff --git a/src/ngLocale/angular-locale_kde-tz.js b/src/ngLocale/angular-locale_kde-tz.js index 58f431e1ef37..c0cfaafc22d5 100644 --- a/src/ngLocale/angular-locale_kde-tz.js +++ b/src/ngLocale/angular-locale_kde-tz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Liduva lyannyano na mavili", "Liduva litandi" ], + "ERANAMES": [ + "Akanapawa Yesu", + "Nankuida Yesu" + ], + "ERAS": [ + "AY", + "NY" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mwedi Ntandi", diff --git a/src/ngLocale/angular-locale_kde.js b/src/ngLocale/angular-locale_kde.js index fddfdb9a0e1a..1a9bfd4daf9e 100644 --- a/src/ngLocale/angular-locale_kde.js +++ b/src/ngLocale/angular-locale_kde.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Liduva lyannyano na mavili", "Liduva litandi" ], + "ERANAMES": [ + "Akanapawa Yesu", + "Nankuida Yesu" + ], + "ERAS": [ + "AY", + "NY" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mwedi Ntandi", diff --git a/src/ngLocale/angular-locale_kea-cv.js b/src/ngLocale/angular-locale_kea-cv.js index 19bd50f279da..1fc8d8e68348 100644 --- a/src/ngLocale/angular-locale_kea-cv.js +++ b/src/ngLocale/angular-locale_kea-cv.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "sesta-fera", "sabadu" ], + "ERANAMES": [ + "Antis di Kristu", + "Dispos di Kristu" + ], + "ERAS": [ + "AK", + "DK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Janeru", diff --git a/src/ngLocale/angular-locale_kea.js b/src/ngLocale/angular-locale_kea.js index d65aabb09ece..0bab114dd5b5 100644 --- a/src/ngLocale/angular-locale_kea.js +++ b/src/ngLocale/angular-locale_kea.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "sesta-fera", "sabadu" ], + "ERANAMES": [ + "Antis di Kristu", + "Dispos di Kristu" + ], + "ERAS": [ + "AK", + "DK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Janeru", diff --git a/src/ngLocale/angular-locale_khq-ml.js b/src/ngLocale/angular-locale_khq-ml.js index 454b9d005be0..328809e19552 100644 --- a/src/ngLocale/angular-locale_khq-ml.js +++ b/src/ngLocale/angular-locale_khq-ml.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Aljuma", "Assabdu" ], + "ERANAMES": [ + "Isaa jine", + "Isaa jamanoo" + ], + "ERAS": [ + "IJ", + "IZ" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u017danwiye", diff --git a/src/ngLocale/angular-locale_khq.js b/src/ngLocale/angular-locale_khq.js index b7687dc4c0af..90fa7e6bb33c 100644 --- a/src/ngLocale/angular-locale_khq.js +++ b/src/ngLocale/angular-locale_khq.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Aljuma", "Assabdu" ], + "ERANAMES": [ + "Isaa jine", + "Isaa jamanoo" + ], + "ERAS": [ + "IJ", + "IZ" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u017danwiye", diff --git a/src/ngLocale/angular-locale_ki-ke.js b/src/ngLocale/angular-locale_ki-ke.js index ce9096c01ab5..5b06cd7bdc96 100644 --- a/src/ngLocale/angular-locale_ki-ke.js +++ b/src/ngLocale/angular-locale_ki-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Njumaa", "Njumamothi" ], + "ERANAMES": [ + "Mbere ya Kristo", + "Thutha wa Kristo" + ], + "ERAS": [ + "MK", + "TK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Njenuar\u0129", diff --git a/src/ngLocale/angular-locale_ki.js b/src/ngLocale/angular-locale_ki.js index 24625ecaa6ef..d0fe6b04c95b 100644 --- a/src/ngLocale/angular-locale_ki.js +++ b/src/ngLocale/angular-locale_ki.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Njumaa", "Njumamothi" ], + "ERANAMES": [ + "Mbere ya Kristo", + "Thutha wa Kristo" + ], + "ERAS": [ + "MK", + "TK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Njenuar\u0129", diff --git a/src/ngLocale/angular-locale_kk-cyrl-kz.js b/src/ngLocale/angular-locale_kk-cyrl-kz.js index 2d9409e673a9..828abbf4f6f8 100644 --- a/src/ngLocale/angular-locale_kk-cyrl-kz.js +++ b/src/ngLocale/angular-locale_kk-cyrl-kz.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0436\u04b1\u043c\u0430", "\u0441\u0435\u043d\u0431\u0456" ], + "ERANAMES": [ + "\u0411\u0456\u0437\u0434\u0456\u04a3 \u0437\u0430\u043c\u0430\u043d\u044b\u043c\u044b\u0437\u0493\u0430 \u0434\u0435\u0439\u0456\u043d", + "\u0411\u0456\u0437\u0434\u0456\u04a3 \u0437\u0430\u043c\u0430\u043d\u044b\u043c\u044b\u0437" + ], + "ERAS": [ + "\u0431.\u0437.\u0434.", + "\u0431.\u0437." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u049b\u0430\u04a3\u0442\u0430\u0440", diff --git a/src/ngLocale/angular-locale_kk-cyrl.js b/src/ngLocale/angular-locale_kk-cyrl.js index 48070c053a00..1dc33f3dea29 100644 --- a/src/ngLocale/angular-locale_kk-cyrl.js +++ b/src/ngLocale/angular-locale_kk-cyrl.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0436\u04b1\u043c\u0430", "\u0441\u0435\u043d\u0431\u0456" ], + "ERANAMES": [ + "\u0411\u0456\u0437\u0434\u0456\u04a3 \u0437\u0430\u043c\u0430\u043d\u044b\u043c\u044b\u0437\u0493\u0430 \u0434\u0435\u0439\u0456\u043d", + "\u0411\u0456\u0437\u0434\u0456\u04a3 \u0437\u0430\u043c\u0430\u043d\u044b\u043c\u044b\u0437" + ], + "ERAS": [ + "\u0431.\u0437.\u0434.", + "\u0431.\u0437." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u049b\u0430\u04a3\u0442\u0430\u0440", diff --git a/src/ngLocale/angular-locale_kk.js b/src/ngLocale/angular-locale_kk.js index 2170d13815c4..3d4a44e0c7e1 100644 --- a/src/ngLocale/angular-locale_kk.js +++ b/src/ngLocale/angular-locale_kk.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0436\u04b1\u043c\u0430", "\u0441\u0435\u043d\u0431\u0456" ], + "ERANAMES": [ + "\u0411\u0456\u0437\u0434\u0456\u04a3 \u0437\u0430\u043c\u0430\u043d\u044b\u043c\u044b\u0437\u0493\u0430 \u0434\u0435\u0439\u0456\u043d", + "\u0411\u0456\u0437\u0434\u0456\u04a3 \u0437\u0430\u043c\u0430\u043d\u044b\u043c\u044b\u0437" + ], + "ERAS": [ + "\u0431.\u0437.\u0434.", + "\u0431.\u0437." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u049b\u0430\u04a3\u0442\u0430\u0440", diff --git a/src/ngLocale/angular-locale_kkj-cm.js b/src/ngLocale/angular-locale_kkj-cm.js index 06bf8e6fcb3c..8411198b652e 100644 --- a/src/ngLocale/angular-locale_kkj-cm.js +++ b/src/ngLocale/angular-locale_kkj-cm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "va\u014bd\u025br\u025bdi", "m\u0254n\u0254 s\u0254ndi" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "pamba", diff --git a/src/ngLocale/angular-locale_kkj.js b/src/ngLocale/angular-locale_kkj.js index f16050626734..07bdf0446804 100644 --- a/src/ngLocale/angular-locale_kkj.js +++ b/src/ngLocale/angular-locale_kkj.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "va\u014bd\u025br\u025bdi", "m\u0254n\u0254 s\u0254ndi" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "pamba", diff --git a/src/ngLocale/angular-locale_kl-gl.js b/src/ngLocale/angular-locale_kl-gl.js index 54d239a0c4ed..3b3e77d0433b 100644 --- a/src/ngLocale/angular-locale_kl-gl.js +++ b/src/ngLocale/angular-locale_kl-gl.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "tallimanngorneq", "arfininngorneq" ], + "ERANAMES": [ + "Kristusip inunngornerata siornagut", + "Kristusip inunngornerata kingornagut" + ], + "ERAS": [ + "Kr.in.si.", + "Kr.in.king." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januari", diff --git a/src/ngLocale/angular-locale_kl.js b/src/ngLocale/angular-locale_kl.js index d22e1dfb2cea..a20a1950b4d3 100644 --- a/src/ngLocale/angular-locale_kl.js +++ b/src/ngLocale/angular-locale_kl.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "tallimanngorneq", "arfininngorneq" ], + "ERANAMES": [ + "Kristusip inunngornerata siornagut", + "Kristusip inunngornerata kingornagut" + ], + "ERAS": [ + "Kr.in.si.", + "Kr.in.king." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januari", diff --git a/src/ngLocale/angular-locale_kln-ke.js b/src/ngLocale/angular-locale_kln-ke.js index e7d97b3062d1..407272d48997 100644 --- a/src/ngLocale/angular-locale_kln-ke.js +++ b/src/ngLocale/angular-locale_kln-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Betutab mut", "Betutab lo" ], + "ERANAMES": [ + "Amait kesich Jesu", + "Kokakesich Jesu" + ], + "ERAS": [ + "AM", + "KO" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mulgul", diff --git a/src/ngLocale/angular-locale_kln.js b/src/ngLocale/angular-locale_kln.js index e5b54c7affca..b6e7b47108a6 100644 --- a/src/ngLocale/angular-locale_kln.js +++ b/src/ngLocale/angular-locale_kln.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Betutab mut", "Betutab lo" ], + "ERANAMES": [ + "Amait kesich Jesu", + "Kokakesich Jesu" + ], + "ERAS": [ + "AM", + "KO" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mulgul", diff --git a/src/ngLocale/angular-locale_km-kh.js b/src/ngLocale/angular-locale_km-kh.js index 10d48302826e..b8ded02dcae2 100644 --- a/src/ngLocale/angular-locale_km-kh.js +++ b/src/ngLocale/angular-locale_km-kh.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u179f\u17bb\u1780\u17d2\u179a", "\u179f\u17c5\u179a\u17cd" ], + "ERANAMES": [ + "\u1798\u17bb\u1793\u200b\u1782\u17d2\u179a\u17b7\u179f\u17d2\u178f\u179f\u1780\u179a\u17b6\u1787", + "\u1782\u17d2\u179a\u17b7\u179f\u17d2\u178f\u179f\u1780\u179a\u17b6\u1787" + ], + "ERAS": [ + "\u1798\u17bb\u1793 \u1782.\u179f.", + "\u1782.\u179f." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u1798\u1780\u179a\u17b6", diff --git a/src/ngLocale/angular-locale_km.js b/src/ngLocale/angular-locale_km.js index 03a557afc859..88d1e947f3c3 100644 --- a/src/ngLocale/angular-locale_km.js +++ b/src/ngLocale/angular-locale_km.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u179f\u17bb\u1780\u17d2\u179a", "\u179f\u17c5\u179a\u17cd" ], + "ERANAMES": [ + "\u1798\u17bb\u1793\u200b\u1782\u17d2\u179a\u17b7\u179f\u17d2\u178f\u179f\u1780\u179a\u17b6\u1787", + "\u1782\u17d2\u179a\u17b7\u179f\u17d2\u178f\u179f\u1780\u179a\u17b6\u1787" + ], + "ERAS": [ + "\u1798\u17bb\u1793 \u1782.\u179f.", + "\u1782.\u179f." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u1798\u1780\u179a\u17b6", diff --git a/src/ngLocale/angular-locale_kn-in.js b/src/ngLocale/angular-locale_kn-in.js index 105d028f691c..6dbd7a8029b6 100644 --- a/src/ngLocale/angular-locale_kn-in.js +++ b/src/ngLocale/angular-locale_kn-in.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0cb6\u0cc1\u0c95\u0ccd\u0cb0\u0cb5\u0cbe\u0cb0", "\u0cb6\u0ca8\u0cbf\u0cb5\u0cbe\u0cb0" ], + "ERANAMES": [ + "\u0c95\u0ccd\u0cb0\u0cbf\u0cb8\u0ccd\u0ca4 \u0caa\u0cc2\u0cb0\u0ccd\u0cb5", + "\u0c95\u0ccd\u0cb0\u0cbf\u0cb8\u0ccd\u0ca4 \u0cb6\u0c95" + ], + "ERAS": [ + "\u0c95\u0ccd\u0cb0\u0cbf.\u0caa\u0cc2", + "\u0c95\u0ccd\u0cb0\u0cbf.\u0cb6" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0c9c\u0ca8\u0cb5\u0cb0\u0cbf", diff --git a/src/ngLocale/angular-locale_kn.js b/src/ngLocale/angular-locale_kn.js index 2cd98d84455b..2cb656baa7e9 100644 --- a/src/ngLocale/angular-locale_kn.js +++ b/src/ngLocale/angular-locale_kn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0cb6\u0cc1\u0c95\u0ccd\u0cb0\u0cb5\u0cbe\u0cb0", "\u0cb6\u0ca8\u0cbf\u0cb5\u0cbe\u0cb0" ], + "ERANAMES": [ + "\u0c95\u0ccd\u0cb0\u0cbf\u0cb8\u0ccd\u0ca4 \u0caa\u0cc2\u0cb0\u0ccd\u0cb5", + "\u0c95\u0ccd\u0cb0\u0cbf\u0cb8\u0ccd\u0ca4 \u0cb6\u0c95" + ], + "ERAS": [ + "\u0c95\u0ccd\u0cb0\u0cbf.\u0caa\u0cc2", + "\u0c95\u0ccd\u0cb0\u0cbf.\u0cb6" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0c9c\u0ca8\u0cb5\u0cb0\u0cbf", diff --git a/src/ngLocale/angular-locale_ko-kp.js b/src/ngLocale/angular-locale_ko-kp.js index 65dc29b200ac..5cc049fabc64 100644 --- a/src/ngLocale/angular-locale_ko-kp.js +++ b/src/ngLocale/angular-locale_ko-kp.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\uae08\uc694\uc77c", "\ud1a0\uc694\uc77c" ], + "ERANAMES": [ + "\uae30\uc6d0\uc804", + "\uc11c\uae30" + ], + "ERAS": [ + "\uae30\uc6d0\uc804", + "\uc11c\uae30" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "1\uc6d4", diff --git a/src/ngLocale/angular-locale_ko-kr.js b/src/ngLocale/angular-locale_ko-kr.js index 13290cf27f2b..bcb418142ec0 100644 --- a/src/ngLocale/angular-locale_ko-kr.js +++ b/src/ngLocale/angular-locale_ko-kr.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\uae08\uc694\uc77c", "\ud1a0\uc694\uc77c" ], + "ERANAMES": [ + "\uae30\uc6d0\uc804", + "\uc11c\uae30" + ], + "ERAS": [ + "\uae30\uc6d0\uc804", + "\uc11c\uae30" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "1\uc6d4", diff --git a/src/ngLocale/angular-locale_ko.js b/src/ngLocale/angular-locale_ko.js index 9c0f2624f99e..efbf90eabf03 100644 --- a/src/ngLocale/angular-locale_ko.js +++ b/src/ngLocale/angular-locale_ko.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\uae08\uc694\uc77c", "\ud1a0\uc694\uc77c" ], + "ERANAMES": [ + "\uae30\uc6d0\uc804", + "\uc11c\uae30" + ], + "ERAS": [ + "\uae30\uc6d0\uc804", + "\uc11c\uae30" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "1\uc6d4", diff --git a/src/ngLocale/angular-locale_kok-in.js b/src/ngLocale/angular-locale_kok-in.js index 224b85f2814b..b0ca4d029e1d 100644 --- a/src/ngLocale/angular-locale_kok-in.js +++ b/src/ngLocale/angular-locale_kok-in.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930", "\u0936\u0928\u093f\u0935\u093e\u0930" ], + "ERANAMES": [ + "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u092a\u0942\u0930\u094d\u0935", + "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u0936\u0916\u093e" + ], + "ERAS": [ + "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u092a\u0942\u0930\u094d\u0935", + "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u0936\u0916\u093e" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940", diff --git a/src/ngLocale/angular-locale_kok.js b/src/ngLocale/angular-locale_kok.js index e463ca06bfb9..e67af3a57bea 100644 --- a/src/ngLocale/angular-locale_kok.js +++ b/src/ngLocale/angular-locale_kok.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930", "\u0936\u0928\u093f\u0935\u093e\u0930" ], + "ERANAMES": [ + "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u092a\u0942\u0930\u094d\u0935", + "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u0936\u0916\u093e" + ], + "ERAS": [ + "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u092a\u0942\u0930\u094d\u0935", + "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u0936\u0916\u093e" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940", diff --git a/src/ngLocale/angular-locale_ks-arab-in.js b/src/ngLocale/angular-locale_ks-arab-in.js index acb8bca673ae..170a154e305a 100644 --- a/src/ngLocale/angular-locale_ks-arab-in.js +++ b/src/ngLocale/angular-locale_ks-arab-in.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u062c\u064f\u0645\u06c1", "\u0628\u0679\u0648\u0627\u0631" ], + "ERANAMES": [ + "\u0642\u0628\u0655\u0644 \u0645\u0633\u06cc\u0656\u062d", + "\u0639\u06cc\u0656\u0633\u0648\u06cc \u0633\u0646\u06c1\u0655" + ], + "ERAS": [ + "\u0628\u06cc \u0633\u06cc", + "\u0627\u06d2 \u0688\u06cc" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u062c\u0646\u0624\u0631\u06cc", diff --git a/src/ngLocale/angular-locale_ks-arab.js b/src/ngLocale/angular-locale_ks-arab.js index 2221bae92b95..04ffc2106452 100644 --- a/src/ngLocale/angular-locale_ks-arab.js +++ b/src/ngLocale/angular-locale_ks-arab.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u062c\u064f\u0645\u06c1", "\u0628\u0679\u0648\u0627\u0631" ], + "ERANAMES": [ + "\u0642\u0628\u0655\u0644 \u0645\u0633\u06cc\u0656\u062d", + "\u0639\u06cc\u0656\u0633\u0648\u06cc \u0633\u0646\u06c1\u0655" + ], + "ERAS": [ + "\u0628\u06cc \u0633\u06cc", + "\u0627\u06d2 \u0688\u06cc" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u062c\u0646\u0624\u0631\u06cc", diff --git a/src/ngLocale/angular-locale_ks.js b/src/ngLocale/angular-locale_ks.js index d4fcda4fb86e..4167261c53b4 100644 --- a/src/ngLocale/angular-locale_ks.js +++ b/src/ngLocale/angular-locale_ks.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u062c\u064f\u0645\u06c1", "\u0628\u0679\u0648\u0627\u0631" ], + "ERANAMES": [ + "\u0642\u0628\u0655\u0644 \u0645\u0633\u06cc\u0656\u062d", + "\u0639\u06cc\u0656\u0633\u0648\u06cc \u0633\u0646\u06c1\u0655" + ], + "ERAS": [ + "\u0628\u06cc \u0633\u06cc", + "\u0627\u06d2 \u0688\u06cc" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u062c\u0646\u0624\u0631\u06cc", diff --git a/src/ngLocale/angular-locale_ksb-tz.js b/src/ngLocale/angular-locale_ksb-tz.js index 9154f5c97ace..f52a6f36252d 100644 --- a/src/ngLocale/angular-locale_ksb-tz.js +++ b/src/ngLocale/angular-locale_ksb-tz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumaamosi" ], + "ERANAMES": [ + "Kabla ya Klisto", + "Baada ya Klisto" + ], + "ERAS": [ + "KK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januali", diff --git a/src/ngLocale/angular-locale_ksb.js b/src/ngLocale/angular-locale_ksb.js index 9bbd6962896a..145289260197 100644 --- a/src/ngLocale/angular-locale_ksb.js +++ b/src/ngLocale/angular-locale_ksb.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumaamosi" ], + "ERANAMES": [ + "Kabla ya Klisto", + "Baada ya Klisto" + ], + "ERAS": [ + "KK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januali", diff --git a/src/ngLocale/angular-locale_ksf-cm.js b/src/ngLocale/angular-locale_ksf-cm.js index 062b8a2239a5..a3f69547b074 100644 --- a/src/ngLocale/angular-locale_ksf-cm.js +++ b/src/ngLocale/angular-locale_ksf-cm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "j\u00famb\u00e1", "samd\u00ed" ], + "ERANAMES": [ + "di Y\u025b\u0301sus ak\u00e1 y\u00e1l\u025b", + "c\u00e1m\u025b\u025bn k\u01dd k\u01ddb\u0254pka Y" + ], + "ERAS": [ + "d.Y.", + "k.Y." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u014bw\u00ed\u00ed a nt\u0254\u0301nt\u0254", diff --git a/src/ngLocale/angular-locale_ksf.js b/src/ngLocale/angular-locale_ksf.js index 71977daba95e..dfd65a2e4457 100644 --- a/src/ngLocale/angular-locale_ksf.js +++ b/src/ngLocale/angular-locale_ksf.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "j\u00famb\u00e1", "samd\u00ed" ], + "ERANAMES": [ + "di Y\u025b\u0301sus ak\u00e1 y\u00e1l\u025b", + "c\u00e1m\u025b\u025bn k\u01dd k\u01ddb\u0254pka Y" + ], + "ERAS": [ + "d.Y.", + "k.Y." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u014bw\u00ed\u00ed a nt\u0254\u0301nt\u0254", diff --git a/src/ngLocale/angular-locale_ksh-de.js b/src/ngLocale/angular-locale_ksh-de.js index 2869b894fe22..c69f40d7430a 100644 --- a/src/ngLocale/angular-locale_ksh-de.js +++ b/src/ngLocale/angular-locale_ksh-de.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friidaach", "Samsdaach" ], + "ERANAMES": [ + "v\u00fcr Chrestus", + "noh Chrestus" + ], + "ERAS": [ + "v. Chr.", + "n. Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Jannewa", diff --git a/src/ngLocale/angular-locale_ksh.js b/src/ngLocale/angular-locale_ksh.js index 765695ece70f..cb166982d715 100644 --- a/src/ngLocale/angular-locale_ksh.js +++ b/src/ngLocale/angular-locale_ksh.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Friidaach", "Samsdaach" ], + "ERANAMES": [ + "v\u00fcr Chrestus", + "noh Chrestus" + ], + "ERAS": [ + "v. Chr.", + "n. Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Jannewa", diff --git a/src/ngLocale/angular-locale_kw-gb.js b/src/ngLocale/angular-locale_kw-gb.js index 8a71c607da3a..90bc5f1df983 100644 --- a/src/ngLocale/angular-locale_kw-gb.js +++ b/src/ngLocale/angular-locale_kw-gb.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "De Gwener", "De Sadorn" ], + "ERANAMES": [ + "RC", + "AD" + ], + "ERAS": [ + "RC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mys Genver", diff --git a/src/ngLocale/angular-locale_kw.js b/src/ngLocale/angular-locale_kw.js index a6be53d6f5ca..94eb8de79e74 100644 --- a/src/ngLocale/angular-locale_kw.js +++ b/src/ngLocale/angular-locale_kw.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "De Gwener", "De Sadorn" ], + "ERANAMES": [ + "RC", + "AD" + ], + "ERAS": [ + "RC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mys Genver", diff --git a/src/ngLocale/angular-locale_ky-cyrl-kg.js b/src/ngLocale/angular-locale_ky-cyrl-kg.js index 97695c2b3b1d..75a594719d95 100644 --- a/src/ngLocale/angular-locale_ky-cyrl-kg.js +++ b/src/ngLocale/angular-locale_ky-cyrl-kg.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0436\u0443\u043c\u0430", "\u0438\u0448\u0435\u043c\u0431\u0438" ], + "ERANAMES": [ + "\u0431\u0438\u0437\u0434\u0438\u043d \u0437\u0430\u043c\u0430\u043d\u0433\u0430 \u0447\u0435\u0439\u0438\u043d", + "\u0431\u0438\u0437\u0434\u0438\u043d \u0437\u0430\u043c\u0430\u043d" + ], + "ERAS": [ + "\u0431.\u0437.\u0447.", + "\u0431.\u0437." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u044f\u043d\u0432\u0430\u0440\u044c", diff --git a/src/ngLocale/angular-locale_ky-cyrl.js b/src/ngLocale/angular-locale_ky-cyrl.js index cbd7481b5651..d1af6a48ab2f 100644 --- a/src/ngLocale/angular-locale_ky-cyrl.js +++ b/src/ngLocale/angular-locale_ky-cyrl.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0436\u0443\u043c\u0430", "\u0438\u0448\u0435\u043c\u0431\u0438" ], + "ERANAMES": [ + "\u0431\u0438\u0437\u0434\u0438\u043d \u0437\u0430\u043c\u0430\u043d\u0433\u0430 \u0447\u0435\u0439\u0438\u043d", + "\u0431\u0438\u0437\u0434\u0438\u043d \u0437\u0430\u043c\u0430\u043d" + ], + "ERAS": [ + "\u0431.\u0437.\u0447.", + "\u0431.\u0437." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u044f\u043d\u0432\u0430\u0440\u044c", diff --git a/src/ngLocale/angular-locale_ky.js b/src/ngLocale/angular-locale_ky.js index a2c2ef1245d1..b7fe26351d5a 100644 --- a/src/ngLocale/angular-locale_ky.js +++ b/src/ngLocale/angular-locale_ky.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0436\u0443\u043c\u0430", "\u0438\u0448\u0435\u043c\u0431\u0438" ], + "ERANAMES": [ + "\u0431\u0438\u0437\u0434\u0438\u043d \u0437\u0430\u043c\u0430\u043d\u0433\u0430 \u0447\u0435\u0439\u0438\u043d", + "\u0431\u0438\u0437\u0434\u0438\u043d \u0437\u0430\u043c\u0430\u043d" + ], + "ERAS": [ + "\u0431.\u0437.\u0447.", + "\u0431.\u0437." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u044f\u043d\u0432\u0430\u0440\u044c", diff --git a/src/ngLocale/angular-locale_lag-tz.js b/src/ngLocale/angular-locale_lag-tz.js index 4dabec384ddb..d260343b21d3 100644 --- a/src/ngLocale/angular-locale_lag-tz.js +++ b/src/ngLocale/angular-locale_lag-tz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijum\u00e1a", "Jumam\u00f3osi" ], + "ERANAMES": [ + "K\u0268r\u0268sit\u0289 s\u0268 anavyaal", + "K\u0268r\u0268sit\u0289 akavyaalwe" + ], + "ERAS": [ + "KSA", + "KA" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "K\u0289f\u00fangat\u0268", diff --git a/src/ngLocale/angular-locale_lag.js b/src/ngLocale/angular-locale_lag.js index 46e2afaac1ac..f349e042d3cf 100644 --- a/src/ngLocale/angular-locale_lag.js +++ b/src/ngLocale/angular-locale_lag.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijum\u00e1a", "Jumam\u00f3osi" ], + "ERANAMES": [ + "K\u0268r\u0268sit\u0289 s\u0268 anavyaal", + "K\u0268r\u0268sit\u0289 akavyaalwe" + ], + "ERAS": [ + "KSA", + "KA" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "K\u0289f\u00fangat\u0268", diff --git a/src/ngLocale/angular-locale_lb-lu.js b/src/ngLocale/angular-locale_lb-lu.js index 91cd2e81207f..64ef9776921a 100644 --- a/src/ngLocale/angular-locale_lb-lu.js +++ b/src/ngLocale/angular-locale_lb-lu.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Freideg", "Samschdeg" ], + "ERANAMES": [ + "v. Chr.", + "n. Chr." + ], + "ERAS": [ + "v. Chr.", + "n. Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januar", diff --git a/src/ngLocale/angular-locale_lb.js b/src/ngLocale/angular-locale_lb.js index be8bace6d7c9..dd721993738a 100644 --- a/src/ngLocale/angular-locale_lb.js +++ b/src/ngLocale/angular-locale_lb.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Freideg", "Samschdeg" ], + "ERANAMES": [ + "v. Chr.", + "n. Chr." + ], + "ERAS": [ + "v. Chr.", + "n. Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januar", diff --git a/src/ngLocale/angular-locale_lg-ug.js b/src/ngLocale/angular-locale_lg-ug.js index f85178e7e8b1..78d1c9f0be6f 100644 --- a/src/ngLocale/angular-locale_lg-ug.js +++ b/src/ngLocale/angular-locale_lg-ug.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Lwakutaano", "Lwamukaaga" ], + "ERANAMES": [ + "Kulisito nga tannaza", + "Bukya Kulisito Azaal" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Janwaliyo", diff --git a/src/ngLocale/angular-locale_lg.js b/src/ngLocale/angular-locale_lg.js index 5355a634135f..e0bbf02f1fe9 100644 --- a/src/ngLocale/angular-locale_lg.js +++ b/src/ngLocale/angular-locale_lg.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Lwakutaano", "Lwamukaaga" ], + "ERANAMES": [ + "Kulisito nga tannaza", + "Bukya Kulisito Azaal" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Janwaliyo", diff --git a/src/ngLocale/angular-locale_lkt-us.js b/src/ngLocale/angular-locale_lkt-us.js index 8f5cf94b9982..e9a83adc5365 100644 --- a/src/ngLocale/angular-locale_lkt-us.js +++ b/src/ngLocale/angular-locale_lkt-us.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "A\u014bp\u00e9tuzapta\u014b", "Ow\u00e1\u014bgyu\u017ea\u017eapi" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Wi\u00f3the\u021fika W\u00ed", diff --git a/src/ngLocale/angular-locale_lkt.js b/src/ngLocale/angular-locale_lkt.js index b508affb5103..993c345160c0 100644 --- a/src/ngLocale/angular-locale_lkt.js +++ b/src/ngLocale/angular-locale_lkt.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "A\u014bp\u00e9tuzapta\u014b", "Ow\u00e1\u014bgyu\u017ea\u017eapi" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Wi\u00f3the\u021fika W\u00ed", diff --git a/src/ngLocale/angular-locale_ln-ao.js b/src/ngLocale/angular-locale_ln-ao.js index e34e1fdeb495..8a88e889ae03 100644 --- a/src/ngLocale/angular-locale_ln-ao.js +++ b/src/ngLocale/angular-locale_ln-ao.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "mok\u0254l\u0254 ya m\u00edt\u00e1no", "mp\u0254\u0301s\u0254" ], + "ERANAMES": [ + "Yambo ya Y\u00e9zu Kr\u00eds", + "Nsima ya Y\u00e9zu Kr\u00eds" + ], + "ERAS": [ + "lib\u00f3so ya", + "nsima ya Y" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "s\u00e1nz\u00e1 ya yambo", diff --git a/src/ngLocale/angular-locale_ln-cd.js b/src/ngLocale/angular-locale_ln-cd.js index 19cc228a7158..f08e4f4f6643 100644 --- a/src/ngLocale/angular-locale_ln-cd.js +++ b/src/ngLocale/angular-locale_ln-cd.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "mok\u0254l\u0254 ya m\u00edt\u00e1no", "mp\u0254\u0301s\u0254" ], + "ERANAMES": [ + "Yambo ya Y\u00e9zu Kr\u00eds", + "Nsima ya Y\u00e9zu Kr\u00eds" + ], + "ERAS": [ + "lib\u00f3so ya", + "nsima ya Y" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "s\u00e1nz\u00e1 ya yambo", diff --git a/src/ngLocale/angular-locale_ln-cf.js b/src/ngLocale/angular-locale_ln-cf.js index dc8baffc2f96..7af86d5a9272 100644 --- a/src/ngLocale/angular-locale_ln-cf.js +++ b/src/ngLocale/angular-locale_ln-cf.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "mok\u0254l\u0254 ya m\u00edt\u00e1no", "mp\u0254\u0301s\u0254" ], + "ERANAMES": [ + "Yambo ya Y\u00e9zu Kr\u00eds", + "Nsima ya Y\u00e9zu Kr\u00eds" + ], + "ERAS": [ + "lib\u00f3so ya", + "nsima ya Y" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "s\u00e1nz\u00e1 ya yambo", diff --git a/src/ngLocale/angular-locale_ln-cg.js b/src/ngLocale/angular-locale_ln-cg.js index a36b794f721f..5c8e41cd5ada 100644 --- a/src/ngLocale/angular-locale_ln-cg.js +++ b/src/ngLocale/angular-locale_ln-cg.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "mok\u0254l\u0254 ya m\u00edt\u00e1no", "mp\u0254\u0301s\u0254" ], + "ERANAMES": [ + "Yambo ya Y\u00e9zu Kr\u00eds", + "Nsima ya Y\u00e9zu Kr\u00eds" + ], + "ERAS": [ + "lib\u00f3so ya", + "nsima ya Y" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "s\u00e1nz\u00e1 ya yambo", diff --git a/src/ngLocale/angular-locale_ln.js b/src/ngLocale/angular-locale_ln.js index ca569b6a9d8a..300de98e8522 100644 --- a/src/ngLocale/angular-locale_ln.js +++ b/src/ngLocale/angular-locale_ln.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "mok\u0254l\u0254 ya m\u00edt\u00e1no", "mp\u0254\u0301s\u0254" ], + "ERANAMES": [ + "Yambo ya Y\u00e9zu Kr\u00eds", + "Nsima ya Y\u00e9zu Kr\u00eds" + ], + "ERAS": [ + "lib\u00f3so ya", + "nsima ya Y" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "s\u00e1nz\u00e1 ya yambo", diff --git a/src/ngLocale/angular-locale_lo-la.js b/src/ngLocale/angular-locale_lo-la.js index 17c45dc3041c..f6bf34f10749 100644 --- a/src/ngLocale/angular-locale_lo-la.js +++ b/src/ngLocale/angular-locale_lo-la.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0ea7\u0eb1\u0e99\u0eaa\u0eb8\u0e81", "\u0ea7\u0eb1\u0e99\u0ec0\u0eaa\u0ebb\u0eb2" ], + "ERANAMES": [ + "\u0e81\u0ec8\u0ead\u0e99\u0e84\u0ea3\u0eb4\u0e94\u0eaa\u0eb1\u0e81\u0e81\u0eb0\u0ea5\u0eb2\u0e94", + "\u0e84\u0ea3\u0eb4\u0e94\u0eaa\u0eb1\u0e81\u0e81\u0eb0\u0ea5\u0eb2\u0e94" + ], + "ERAS": [ + "\u0e81\u0ec8\u0ead\u0e99 \u0e84.\u0eaa.", + "\u0e84.\u0eaa." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0ea1\u0eb1\u0e87\u0e81\u0ead\u0e99", diff --git a/src/ngLocale/angular-locale_lo.js b/src/ngLocale/angular-locale_lo.js index 3c9e667bac99..76d517543fd8 100644 --- a/src/ngLocale/angular-locale_lo.js +++ b/src/ngLocale/angular-locale_lo.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0ea7\u0eb1\u0e99\u0eaa\u0eb8\u0e81", "\u0ea7\u0eb1\u0e99\u0ec0\u0eaa\u0ebb\u0eb2" ], + "ERANAMES": [ + "\u0e81\u0ec8\u0ead\u0e99\u0e84\u0ea3\u0eb4\u0e94\u0eaa\u0eb1\u0e81\u0e81\u0eb0\u0ea5\u0eb2\u0e94", + "\u0e84\u0ea3\u0eb4\u0e94\u0eaa\u0eb1\u0e81\u0e81\u0eb0\u0ea5\u0eb2\u0e94" + ], + "ERAS": [ + "\u0e81\u0ec8\u0ead\u0e99 \u0e84.\u0eaa.", + "\u0e84.\u0eaa." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0ea1\u0eb1\u0e87\u0e81\u0ead\u0e99", diff --git a/src/ngLocale/angular-locale_lt-lt.js b/src/ngLocale/angular-locale_lt-lt.js index 1147cfb90219..34e16f9d6594 100644 --- a/src/ngLocale/angular-locale_lt-lt.js +++ b/src/ngLocale/angular-locale_lt-lt.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "penktadienis", "\u0161e\u0161tadienis" ], + "ERANAMES": [ + "prie\u0161 Krist\u0173", + "po Kristaus" + ], + "ERAS": [ + "pr. Kr.", + "po Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "sausio", diff --git a/src/ngLocale/angular-locale_lt.js b/src/ngLocale/angular-locale_lt.js index ea9ea7cb17e5..b8f7a9b3df5f 100644 --- a/src/ngLocale/angular-locale_lt.js +++ b/src/ngLocale/angular-locale_lt.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "penktadienis", "\u0161e\u0161tadienis" ], + "ERANAMES": [ + "prie\u0161 Krist\u0173", + "po Kristaus" + ], + "ERAS": [ + "pr. Kr.", + "po Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "sausio", diff --git a/src/ngLocale/angular-locale_lu-cd.js b/src/ngLocale/angular-locale_lu-cd.js index 9b891f0044a1..055332330b53 100644 --- a/src/ngLocale/angular-locale_lu-cd.js +++ b/src/ngLocale/angular-locale_lu-cd.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ng\u00f2vya", "Lubingu" ], + "ERANAMES": [ + "Kumpala kwa Yezu Kli", + "Kunyima kwa Yezu Kli" + ], + "ERAS": [ + "kmp. Y.K.", + "kny. Y. K." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Ciongo", diff --git a/src/ngLocale/angular-locale_lu.js b/src/ngLocale/angular-locale_lu.js index 8a9dfbf452aa..9cddb8fab549 100644 --- a/src/ngLocale/angular-locale_lu.js +++ b/src/ngLocale/angular-locale_lu.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ng\u00f2vya", "Lubingu" ], + "ERANAMES": [ + "Kumpala kwa Yezu Kli", + "Kunyima kwa Yezu Kli" + ], + "ERAS": [ + "kmp. Y.K.", + "kny. Y. K." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Ciongo", diff --git a/src/ngLocale/angular-locale_luo-ke.js b/src/ngLocale/angular-locale_luo-ke.js index f7e8cb2292e3..0f85ee6be2f8 100644 --- a/src/ngLocale/angular-locale_luo-ke.js +++ b/src/ngLocale/angular-locale_luo-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Tich Abich", "Ngeso" ], + "ERANAMES": [ + "Kapok Kristo obiro", + "Ka Kristo osebiro" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Dwe mar Achiel", diff --git a/src/ngLocale/angular-locale_luo.js b/src/ngLocale/angular-locale_luo.js index 9c078b848a49..0067d1f42f45 100644 --- a/src/ngLocale/angular-locale_luo.js +++ b/src/ngLocale/angular-locale_luo.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Tich Abich", "Ngeso" ], + "ERANAMES": [ + "Kapok Kristo obiro", + "Ka Kristo osebiro" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Dwe mar Achiel", diff --git a/src/ngLocale/angular-locale_luy-ke.js b/src/ngLocale/angular-locale_luy-ke.js index 9ac23731269c..301f5bf83775 100644 --- a/src/ngLocale/angular-locale_luy-ke.js +++ b/src/ngLocale/angular-locale_luy-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Murwa wa Katano", "Jumamosi" ], + "ERANAMES": [ + "Imberi ya Kuuza Kwa", + "Muhiga Kuvita Kuuza" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_luy.js b/src/ngLocale/angular-locale_luy.js index 06760719a381..01f683a53d71 100644 --- a/src/ngLocale/angular-locale_luy.js +++ b/src/ngLocale/angular-locale_luy.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Murwa wa Katano", "Jumamosi" ], + "ERANAMES": [ + "Imberi ya Kuuza Kwa", + "Muhiga Kuvita Kuuza" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_lv-lv.js b/src/ngLocale/angular-locale_lv-lv.js index eb5b73201988..c63585488e5d 100644 --- a/src/ngLocale/angular-locale_lv-lv.js +++ b/src/ngLocale/angular-locale_lv-lv.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "piektdiena", "sestdiena" ], + "ERANAMES": [ + "pirms m\u016bsu \u0113ras", + "m\u016bsu \u0113r\u0101" + ], + "ERAS": [ + "p.m.\u0113.", + "m.\u0113." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janv\u0101ris", diff --git a/src/ngLocale/angular-locale_lv.js b/src/ngLocale/angular-locale_lv.js index 0a19f4d9f07a..4a9d4234daad 100644 --- a/src/ngLocale/angular-locale_lv.js +++ b/src/ngLocale/angular-locale_lv.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "piektdiena", "sestdiena" ], + "ERANAMES": [ + "pirms m\u016bsu \u0113ras", + "m\u016bsu \u0113r\u0101" + ], + "ERAS": [ + "p.m.\u0113.", + "m.\u0113." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janv\u0101ris", diff --git a/src/ngLocale/angular-locale_mas-ke.js b/src/ngLocale/angular-locale_mas-ke.js index eece2e446a28..577da2e48ca6 100644 --- a/src/ngLocale/angular-locale_mas-ke.js +++ b/src/ngLocale/angular-locale_mas-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jum\u00e1a", "Jumam\u00f3si" ], + "ERANAMES": [ + "Me\u00edn\u014d Y\u025b\u0301s\u0289", + "E\u00edn\u014d Y\u025b\u0301s\u0289" + ], + "ERAS": [ + "MY", + "EY" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Oladal\u0289\u0301", diff --git a/src/ngLocale/angular-locale_mas-tz.js b/src/ngLocale/angular-locale_mas-tz.js index 36359946bc44..ac2652dde4be 100644 --- a/src/ngLocale/angular-locale_mas-tz.js +++ b/src/ngLocale/angular-locale_mas-tz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jum\u00e1a", "Jumam\u00f3si" ], + "ERANAMES": [ + "Me\u00edn\u014d Y\u025b\u0301s\u0289", + "E\u00edn\u014d Y\u025b\u0301s\u0289" + ], + "ERAS": [ + "MY", + "EY" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Oladal\u0289\u0301", diff --git a/src/ngLocale/angular-locale_mas.js b/src/ngLocale/angular-locale_mas.js index ee220ab2b211..d937c82b9d4a 100644 --- a/src/ngLocale/angular-locale_mas.js +++ b/src/ngLocale/angular-locale_mas.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jum\u00e1a", "Jumam\u00f3si" ], + "ERANAMES": [ + "Me\u00edn\u014d Y\u025b\u0301s\u0289", + "E\u00edn\u014d Y\u025b\u0301s\u0289" + ], + "ERAS": [ + "MY", + "EY" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Oladal\u0289\u0301", diff --git a/src/ngLocale/angular-locale_mer-ke.js b/src/ngLocale/angular-locale_mer-ke.js index 7ab60c515fce..5f464168c847 100644 --- a/src/ngLocale/angular-locale_mer-ke.js +++ b/src/ngLocale/angular-locale_mer-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Wetano", "Jumamosi" ], + "ERANAMES": [ + "Mbere ya Krist\u0169", + "Nyuma ya Krist\u0169" + ], + "ERAS": [ + "MK", + "NK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januar\u0129", diff --git a/src/ngLocale/angular-locale_mer.js b/src/ngLocale/angular-locale_mer.js index af746e526182..4a27ae67b74c 100644 --- a/src/ngLocale/angular-locale_mer.js +++ b/src/ngLocale/angular-locale_mer.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Wetano", "Jumamosi" ], + "ERANAMES": [ + "Mbere ya Krist\u0169", + "Nyuma ya Krist\u0169" + ], + "ERAS": [ + "MK", + "NK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januar\u0129", diff --git a/src/ngLocale/angular-locale_mfe-mu.js b/src/ngLocale/angular-locale_mfe-mu.js index 2ec50de565f0..c36c0a92fa86 100644 --- a/src/ngLocale/angular-locale_mfe-mu.js +++ b/src/ngLocale/angular-locale_mfe-mu.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vandredi", "samdi" ], + "ERANAMES": [ + "avan Zezi-Krist", + "apre Zezi-Krist" + ], + "ERAS": [ + "av. Z-K", + "ap. Z-K" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "zanvie", diff --git a/src/ngLocale/angular-locale_mfe.js b/src/ngLocale/angular-locale_mfe.js index 40cc74392563..f9829c64bfa0 100644 --- a/src/ngLocale/angular-locale_mfe.js +++ b/src/ngLocale/angular-locale_mfe.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vandredi", "samdi" ], + "ERANAMES": [ + "avan Zezi-Krist", + "apre Zezi-Krist" + ], + "ERAS": [ + "av. Z-K", + "ap. Z-K" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "zanvie", diff --git a/src/ngLocale/angular-locale_mg-mg.js b/src/ngLocale/angular-locale_mg-mg.js index 91e07f28a750..05786a908cd6 100644 --- a/src/ngLocale/angular-locale_mg-mg.js +++ b/src/ngLocale/angular-locale_mg-mg.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Zoma", "Asabotsy" ], + "ERANAMES": [ + "Alohan\u2019i JK", + "Aorian\u2019i JK" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Janoary", diff --git a/src/ngLocale/angular-locale_mg.js b/src/ngLocale/angular-locale_mg.js index d3118e48eb5c..086c4e2f1836 100644 --- a/src/ngLocale/angular-locale_mg.js +++ b/src/ngLocale/angular-locale_mg.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Zoma", "Asabotsy" ], + "ERANAMES": [ + "Alohan\u2019i JK", + "Aorian\u2019i JK" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Janoary", diff --git a/src/ngLocale/angular-locale_mgh-mz.js b/src/ngLocale/angular-locale_mgh-mz.js index 56f953d7ff30..2d1357ed3c1f 100644 --- a/src/ngLocale/angular-locale_mgh-mz.js +++ b/src/ngLocale/angular-locale_mgh-mz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Hinapiya yesu", + "Yopia yesu" + ], + "ERAS": [ + "HY", + "YY" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mweri wo kwanza", diff --git a/src/ngLocale/angular-locale_mgh.js b/src/ngLocale/angular-locale_mgh.js index 76b5dfc130b9..c7664cc50511 100644 --- a/src/ngLocale/angular-locale_mgh.js +++ b/src/ngLocale/angular-locale_mgh.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Hinapiya yesu", + "Yopia yesu" + ], + "ERAS": [ + "HY", + "YY" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mweri wo kwanza", diff --git a/src/ngLocale/angular-locale_mgo-cm.js b/src/ngLocale/angular-locale_mgo-cm.js index 409c5612bf12..316a404be7b1 100644 --- a/src/ngLocale/angular-locale_mgo-cm.js +++ b/src/ngLocale/angular-locale_mgo-cm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Aneg 6", "Aneg 7" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "im\u0259g mbegtug", diff --git a/src/ngLocale/angular-locale_mgo.js b/src/ngLocale/angular-locale_mgo.js index 362b3247b2be..ae824f45cc16 100644 --- a/src/ngLocale/angular-locale_mgo.js +++ b/src/ngLocale/angular-locale_mgo.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Aneg 6", "Aneg 7" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "im\u0259g mbegtug", diff --git a/src/ngLocale/angular-locale_mk-mk.js b/src/ngLocale/angular-locale_mk-mk.js index 2d50edb281ff..049204a64910 100644 --- a/src/ngLocale/angular-locale_mk-mk.js +++ b/src/ngLocale/angular-locale_mk-mk.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u0435\u0442\u043e\u043a", "\u0441\u0430\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u043f\u0440\u0435\u0434 \u043d\u0430\u0448\u0430\u0442\u0430 \u0435\u0440\u0430", + "\u043e\u0434 \u043d\u0430\u0448\u0430\u0442\u0430 \u0435\u0440\u0430" + ], + "ERAS": [ + "\u043f\u0440.\u043d.\u0435.", + "\u043d.\u0435." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0458\u0430\u043d\u0443\u0430\u0440\u0438", diff --git a/src/ngLocale/angular-locale_mk.js b/src/ngLocale/angular-locale_mk.js index 14454e5cb39a..7cb62ffd8b61 100644 --- a/src/ngLocale/angular-locale_mk.js +++ b/src/ngLocale/angular-locale_mk.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u0435\u0442\u043e\u043a", "\u0441\u0430\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u043f\u0440\u0435\u0434 \u043d\u0430\u0448\u0430\u0442\u0430 \u0435\u0440\u0430", + "\u043e\u0434 \u043d\u0430\u0448\u0430\u0442\u0430 \u0435\u0440\u0430" + ], + "ERAS": [ + "\u043f\u0440.\u043d.\u0435.", + "\u043d.\u0435." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0458\u0430\u043d\u0443\u0430\u0440\u0438", diff --git a/src/ngLocale/angular-locale_ml-in.js b/src/ngLocale/angular-locale_ml-in.js index bcd187cb703e..09a131c7a32b 100644 --- a/src/ngLocale/angular-locale_ml-in.js +++ b/src/ngLocale/angular-locale_ml-in.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0d35\u0d46\u0d33\u0d4d\u0d33\u0d3f\u0d2f\u0d3e\u0d34\u0d4d\u200c\u0d1a", "\u0d36\u0d28\u0d3f\u0d2f\u0d3e\u0d34\u0d4d\u200c\u0d1a" ], + "ERANAMES": [ + "\u0d15\u0d4d\u0d30\u0d3f\u0d38\u0d4d\u200c\u0d24\u0d41\u0d35\u0d3f\u0d28\u0d4d \u0d2e\u0d41\u0d2e\u0d4d\u0d2a\u0d4d", + "\u0d06\u0d28\u0d4d\u0d28\u0d4b \u0d21\u0d4a\u0d2e\u0d3f\u0d28\u0d3f" + ], + "ERAS": [ + "\u0d15\u0d4d\u0d30\u0d3f.\u0d2e\u0d41.", + "\u0d0e\u0d21\u0d3f" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0d1c\u0d28\u0d41\u0d35\u0d30\u0d3f", diff --git a/src/ngLocale/angular-locale_ml.js b/src/ngLocale/angular-locale_ml.js index 985694ec78b9..7951397fb884 100644 --- a/src/ngLocale/angular-locale_ml.js +++ b/src/ngLocale/angular-locale_ml.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0d35\u0d46\u0d33\u0d4d\u0d33\u0d3f\u0d2f\u0d3e\u0d34\u0d4d\u200c\u0d1a", "\u0d36\u0d28\u0d3f\u0d2f\u0d3e\u0d34\u0d4d\u200c\u0d1a" ], + "ERANAMES": [ + "\u0d15\u0d4d\u0d30\u0d3f\u0d38\u0d4d\u200c\u0d24\u0d41\u0d35\u0d3f\u0d28\u0d4d \u0d2e\u0d41\u0d2e\u0d4d\u0d2a\u0d4d", + "\u0d06\u0d28\u0d4d\u0d28\u0d4b \u0d21\u0d4a\u0d2e\u0d3f\u0d28\u0d3f" + ], + "ERAS": [ + "\u0d15\u0d4d\u0d30\u0d3f.\u0d2e\u0d41.", + "\u0d0e\u0d21\u0d3f" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0d1c\u0d28\u0d41\u0d35\u0d30\u0d3f", diff --git a/src/ngLocale/angular-locale_mn-cyrl-mn.js b/src/ngLocale/angular-locale_mn-cyrl-mn.js index 301cc3233120..6bfa3c93dfc2 100644 --- a/src/ngLocale/angular-locale_mn-cyrl-mn.js +++ b/src/ngLocale/angular-locale_mn-cyrl-mn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0431\u0430\u0430\u0441\u0430\u043d", "\u0431\u044f\u043c\u0431\u0430" ], + "ERANAMES": [ + "\u043c\u0430\u043d\u0430\u0439 \u044d\u0440\u0438\u043d\u0438\u0439 \u04e9\u043c\u043d\u04e9\u0445", + "\u043c\u0430\u043d\u0430\u0439 \u044d\u0440\u0438\u043d\u0438\u0439" + ], + "ERAS": [ + "\u041c\u042d\u04e8", + "\u041c\u042d" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u041d\u044d\u0433\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440", diff --git a/src/ngLocale/angular-locale_mn-cyrl.js b/src/ngLocale/angular-locale_mn-cyrl.js index 88e3a90a7f02..177dc837b1d4 100644 --- a/src/ngLocale/angular-locale_mn-cyrl.js +++ b/src/ngLocale/angular-locale_mn-cyrl.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0431\u0430\u0430\u0441\u0430\u043d", "\u0431\u044f\u043c\u0431\u0430" ], + "ERANAMES": [ + "\u043c\u0430\u043d\u0430\u0439 \u044d\u0440\u0438\u043d\u0438\u0439 \u04e9\u043c\u043d\u04e9\u0445", + "\u043c\u0430\u043d\u0430\u0439 \u044d\u0440\u0438\u043d\u0438\u0439" + ], + "ERAS": [ + "\u041c\u042d\u04e8", + "\u041c\u042d" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u041d\u044d\u0433\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440", diff --git a/src/ngLocale/angular-locale_mn.js b/src/ngLocale/angular-locale_mn.js index f098c29a5667..fef91c0c3a47 100644 --- a/src/ngLocale/angular-locale_mn.js +++ b/src/ngLocale/angular-locale_mn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0431\u0430\u0430\u0441\u0430\u043d", "\u0431\u044f\u043c\u0431\u0430" ], + "ERANAMES": [ + "\u043c\u0430\u043d\u0430\u0439 \u044d\u0440\u0438\u043d\u0438\u0439 \u04e9\u043c\u043d\u04e9\u0445", + "\u043c\u0430\u043d\u0430\u0439 \u044d\u0440\u0438\u043d\u0438\u0439" + ], + "ERAS": [ + "\u041c\u042d\u04e8", + "\u041c\u042d" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u041d\u044d\u0433\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440", diff --git a/src/ngLocale/angular-locale_mr-in.js b/src/ngLocale/angular-locale_mr-in.js index dfcc626a14cf..17faf0d4da4b 100644 --- a/src/ngLocale/angular-locale_mr-in.js +++ b/src/ngLocale/angular-locale_mr-in.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930", "\u0936\u0928\u093f\u0935\u093e\u0930" ], + "ERANAMES": [ + "\u0908\u0938\u0935\u0940\u0938\u0928\u092a\u0942\u0930\u094d\u0935", + "\u0908\u0938\u0935\u0940\u0938\u0928" + ], + "ERAS": [ + "\u0907. \u0938. \u092a\u0942.", + "\u0907. \u0938." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940", diff --git a/src/ngLocale/angular-locale_mr.js b/src/ngLocale/angular-locale_mr.js index f871372b637b..df1d95995635 100644 --- a/src/ngLocale/angular-locale_mr.js +++ b/src/ngLocale/angular-locale_mr.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930", "\u0936\u0928\u093f\u0935\u093e\u0930" ], + "ERANAMES": [ + "\u0908\u0938\u0935\u0940\u0938\u0928\u092a\u0942\u0930\u094d\u0935", + "\u0908\u0938\u0935\u0940\u0938\u0928" + ], + "ERAS": [ + "\u0907. \u0938. \u092a\u0942.", + "\u0907. \u0938." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940", diff --git a/src/ngLocale/angular-locale_ms-latn-bn.js b/src/ngLocale/angular-locale_ms-latn-bn.js index 813b030240de..ff3de38e6387 100644 --- a/src/ngLocale/angular-locale_ms-latn-bn.js +++ b/src/ngLocale/angular-locale_ms-latn-bn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Jumaat", "Sabtu" ], + "ERANAMES": [ + "S.M.", + "TM" + ], + "ERAS": [ + "S.M.", + "TM" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_ms-latn-my.js b/src/ngLocale/angular-locale_ms-latn-my.js index 839b7987a674..46f3d23a1f1f 100644 --- a/src/ngLocale/angular-locale_ms-latn-my.js +++ b/src/ngLocale/angular-locale_ms-latn-my.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Jumaat", "Sabtu" ], + "ERANAMES": [ + "S.M.", + "TM" + ], + "ERAS": [ + "S.M.", + "TM" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_ms-latn-sg.js b/src/ngLocale/angular-locale_ms-latn-sg.js index bcfe72da7414..1519728523c9 100644 --- a/src/ngLocale/angular-locale_ms-latn-sg.js +++ b/src/ngLocale/angular-locale_ms-latn-sg.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Jumaat", "Sabtu" ], + "ERANAMES": [ + "S.M.", + "TM" + ], + "ERAS": [ + "S.M.", + "TM" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_ms-latn.js b/src/ngLocale/angular-locale_ms-latn.js index 1fd7ed631de9..f939a50a7e7c 100644 --- a/src/ngLocale/angular-locale_ms-latn.js +++ b/src/ngLocale/angular-locale_ms-latn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Jumaat", "Sabtu" ], + "ERANAMES": [ + "S.M.", + "TM" + ], + "ERAS": [ + "S.M.", + "TM" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_ms.js b/src/ngLocale/angular-locale_ms.js index 5194de3ab9ef..7035785314b6 100644 --- a/src/ngLocale/angular-locale_ms.js +++ b/src/ngLocale/angular-locale_ms.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Jumaat", "Sabtu" ], + "ERANAMES": [ + "S.M.", + "TM" + ], + "ERAS": [ + "S.M.", + "TM" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_mt-mt.js b/src/ngLocale/angular-locale_mt-mt.js index 606cecbd0dff..8ee64155cc8f 100644 --- a/src/ngLocale/angular-locale_mt-mt.js +++ b/src/ngLocale/angular-locale_mt-mt.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Il-\u0120img\u0127a", "Is-Sibt" ], + "ERANAMES": [ + "Qabel Kristu", + "Wara Kristu" + ], + "ERAS": [ + "QK", + "WK" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Jannar", diff --git a/src/ngLocale/angular-locale_mt.js b/src/ngLocale/angular-locale_mt.js index 6edd089db493..a0254605e7cf 100644 --- a/src/ngLocale/angular-locale_mt.js +++ b/src/ngLocale/angular-locale_mt.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Il-\u0120img\u0127a", "Is-Sibt" ], + "ERANAMES": [ + "Qabel Kristu", + "Wara Kristu" + ], + "ERAS": [ + "QK", + "WK" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Jannar", diff --git a/src/ngLocale/angular-locale_mua-cm.js b/src/ngLocale/angular-locale_mua-cm.js index 23f4a418bc67..e5e41d34f3e4 100644 --- a/src/ngLocale/angular-locale_mua-cm.js +++ b/src/ngLocale/angular-locale_mua-cm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Comgaisuu", "Comzye\u0253suu" ], + "ERANAMES": [ + "K\u01ddPel Kristu", + "Pel Kristu" + ], + "ERAS": [ + "KK", + "PK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "F\u0129i Loo", diff --git a/src/ngLocale/angular-locale_mua.js b/src/ngLocale/angular-locale_mua.js index b3959874a0ce..5917047a4699 100644 --- a/src/ngLocale/angular-locale_mua.js +++ b/src/ngLocale/angular-locale_mua.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Comgaisuu", "Comzye\u0253suu" ], + "ERANAMES": [ + "K\u01ddPel Kristu", + "Pel Kristu" + ], + "ERAS": [ + "KK", + "PK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "F\u0129i Loo", diff --git a/src/ngLocale/angular-locale_my-mm.js b/src/ngLocale/angular-locale_my-mm.js index a0351db2ecff..ffe1b4f69502 100644 --- a/src/ngLocale/angular-locale_my-mm.js +++ b/src/ngLocale/angular-locale_my-mm.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u101e\u1031\u102c\u1000\u103c\u102c", "\u1005\u1014\u1031" ], + "ERANAMES": [ + "\u1001\u101b\u1005\u103a\u1010\u1031\u102c\u103a \u1019\u1015\u1031\u102b\u103a\u1019\u102e\u1000\u102c\u101c", + "\u1001\u101b\u1005\u103a\u1010\u1031\u102c\u103a \u1015\u1031\u102b\u103a\u1011\u103d\u1014\u103a\u1038\u1015\u103c\u102e\u1038\u1000\u102c\u101c" + ], + "ERAS": [ + "\u1018\u102e\u1005\u102e", + "\u1021\u1031\u1012\u102e" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u1007\u1014\u103a\u1014\u101d\u102b\u101b\u102e", diff --git a/src/ngLocale/angular-locale_my.js b/src/ngLocale/angular-locale_my.js index 497afc8bfdc3..2181a68d6eb1 100644 --- a/src/ngLocale/angular-locale_my.js +++ b/src/ngLocale/angular-locale_my.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u101e\u1031\u102c\u1000\u103c\u102c", "\u1005\u1014\u1031" ], + "ERANAMES": [ + "\u1001\u101b\u1005\u103a\u1010\u1031\u102c\u103a \u1019\u1015\u1031\u102b\u103a\u1019\u102e\u1000\u102c\u101c", + "\u1001\u101b\u1005\u103a\u1010\u1031\u102c\u103a \u1015\u1031\u102b\u103a\u1011\u103d\u1014\u103a\u1038\u1015\u103c\u102e\u1038\u1000\u102c\u101c" + ], + "ERAS": [ + "\u1018\u102e\u1005\u102e", + "\u1021\u1031\u1012\u102e" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u1007\u1014\u103a\u1014\u101d\u102b\u101b\u102e", diff --git a/src/ngLocale/angular-locale_naq-na.js b/src/ngLocale/angular-locale_naq-na.js index 3bfe4a0bd28f..892bed9a9b1a 100644 --- a/src/ngLocale/angular-locale_naq-na.js +++ b/src/ngLocale/angular-locale_naq-na.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Fraitaxtsees", "Satertaxtsees" ], + "ERANAMES": [ + "Xristub ai\u01c3\u00e2", + "Xristub khao\u01c3g\u00e2" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u01c3Khanni", diff --git a/src/ngLocale/angular-locale_naq.js b/src/ngLocale/angular-locale_naq.js index 116c964073b8..91f3f180696c 100644 --- a/src/ngLocale/angular-locale_naq.js +++ b/src/ngLocale/angular-locale_naq.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Fraitaxtsees", "Satertaxtsees" ], + "ERANAMES": [ + "Xristub ai\u01c3\u00e2", + "Xristub khao\u01c3g\u00e2" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u01c3Khanni", diff --git a/src/ngLocale/angular-locale_nb-no.js b/src/ngLocale/angular-locale_nb-no.js index 22fd95de8238..665ea0d2bde5 100644 --- a/src/ngLocale/angular-locale_nb-no.js +++ b/src/ngLocale/angular-locale_nb-no.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "fredag", "l\u00f8rdag" ], + "ERANAMES": [ + "f.Kr.", + "e.Kr." + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_nb-sj.js b/src/ngLocale/angular-locale_nb-sj.js index 6e2621ce495e..89105f06f1a8 100644 --- a/src/ngLocale/angular-locale_nb-sj.js +++ b/src/ngLocale/angular-locale_nb-sj.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "fredag", "l\u00f8rdag" ], + "ERANAMES": [ + "f.Kr.", + "e.Kr." + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_nb.js b/src/ngLocale/angular-locale_nb.js index 4c771b455c85..c059753f6158 100644 --- a/src/ngLocale/angular-locale_nb.js +++ b/src/ngLocale/angular-locale_nb.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "fredag", "l\u00f8rdag" ], + "ERANAMES": [ + "f.Kr.", + "e.Kr." + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_nd-zw.js b/src/ngLocale/angular-locale_nd-zw.js index ee20ee4e4b93..4a169e1ed64f 100644 --- a/src/ngLocale/angular-locale_nd-zw.js +++ b/src/ngLocale/angular-locale_nd-zw.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Sihlanu", "Mgqibelo" ], + "ERANAMES": [ + "UKristo angakabuyi", + "Ukristo ebuyile" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Zibandlela", diff --git a/src/ngLocale/angular-locale_nd.js b/src/ngLocale/angular-locale_nd.js index 06a5aac10b41..d3f50587fb10 100644 --- a/src/ngLocale/angular-locale_nd.js +++ b/src/ngLocale/angular-locale_nd.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Sihlanu", "Mgqibelo" ], + "ERANAMES": [ + "UKristo angakabuyi", + "Ukristo ebuyile" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Zibandlela", diff --git a/src/ngLocale/angular-locale_ne-in.js b/src/ngLocale/angular-locale_ne-in.js index 85c510f84d87..cc5c88b7d2ac 100644 --- a/src/ngLocale/angular-locale_ne-in.js +++ b/src/ngLocale/angular-locale_ne-in.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930", "\u0936\u0928\u093f\u0935\u093e\u0930" ], + "ERANAMES": [ + "\u0908\u0938\u093e \u092a\u0942\u0930\u094d\u0935", + "\u0938\u0928\u094d" + ], + "ERAS": [ + "\u0908\u0938\u093e \u092a\u0942\u0930\u094d\u0935", + "\u0938\u0928\u094d" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u091c\u0928\u0935\u0930\u0940", diff --git a/src/ngLocale/angular-locale_ne-np.js b/src/ngLocale/angular-locale_ne-np.js index 03734caf294a..4ac6a7396360 100644 --- a/src/ngLocale/angular-locale_ne-np.js +++ b/src/ngLocale/angular-locale_ne-np.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0936\u0941\u0915\u094d\u0930\u092c\u093e\u0930", "\u0936\u0928\u093f\u092c\u093e\u0930" ], + "ERANAMES": [ + "\u0908\u0938\u093e \u092a\u0942\u0930\u094d\u0935", + "\u0938\u0928\u094d" + ], + "ERAS": [ + "\u0908\u0938\u093e \u092a\u0942\u0930\u094d\u0935", + "\u0938\u0928\u094d" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u091c\u0928\u0935\u0930\u0940", diff --git a/src/ngLocale/angular-locale_ne.js b/src/ngLocale/angular-locale_ne.js index 6c9f48c74a63..9a679682b4be 100644 --- a/src/ngLocale/angular-locale_ne.js +++ b/src/ngLocale/angular-locale_ne.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0936\u0941\u0915\u094d\u0930\u092c\u093e\u0930", "\u0936\u0928\u093f\u092c\u093e\u0930" ], + "ERANAMES": [ + "\u0908\u0938\u093e \u092a\u0942\u0930\u094d\u0935", + "\u0938\u0928\u094d" + ], + "ERAS": [ + "\u0908\u0938\u093e \u092a\u0942\u0930\u094d\u0935", + "\u0938\u0928\u094d" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u091c\u0928\u0935\u0930\u0940", diff --git a/src/ngLocale/angular-locale_nl-aw.js b/src/ngLocale/angular-locale_nl-aw.js index 8279c2881dc7..4caaf01c303d 100644 --- a/src/ngLocale/angular-locale_nl-aw.js +++ b/src/ngLocale/angular-locale_nl-aw.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vrijdag", "zaterdag" ], + "ERANAMES": [ + "voor Christus", + "na Christus" + ], + "ERAS": [ + "v.Chr.", + "n.Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januari", diff --git a/src/ngLocale/angular-locale_nl-be.js b/src/ngLocale/angular-locale_nl-be.js index a99310d85879..07829bc3e5b6 100644 --- a/src/ngLocale/angular-locale_nl-be.js +++ b/src/ngLocale/angular-locale_nl-be.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vrijdag", "zaterdag" ], + "ERANAMES": [ + "voor Christus", + "na Christus" + ], + "ERAS": [ + "v.Chr.", + "n.Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januari", diff --git a/src/ngLocale/angular-locale_nl-bq.js b/src/ngLocale/angular-locale_nl-bq.js index c138630fb9f6..06fcd12866fd 100644 --- a/src/ngLocale/angular-locale_nl-bq.js +++ b/src/ngLocale/angular-locale_nl-bq.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vrijdag", "zaterdag" ], + "ERANAMES": [ + "voor Christus", + "na Christus" + ], + "ERAS": [ + "v.Chr.", + "n.Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januari", diff --git a/src/ngLocale/angular-locale_nl-cw.js b/src/ngLocale/angular-locale_nl-cw.js index a35a1790d8de..2e28b2bb59d0 100644 --- a/src/ngLocale/angular-locale_nl-cw.js +++ b/src/ngLocale/angular-locale_nl-cw.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vrijdag", "zaterdag" ], + "ERANAMES": [ + "voor Christus", + "na Christus" + ], + "ERAS": [ + "v.Chr.", + "n.Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januari", diff --git a/src/ngLocale/angular-locale_nl-nl.js b/src/ngLocale/angular-locale_nl-nl.js index 3c45e40e1af2..5b93f19085ab 100644 --- a/src/ngLocale/angular-locale_nl-nl.js +++ b/src/ngLocale/angular-locale_nl-nl.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vrijdag", "zaterdag" ], + "ERANAMES": [ + "voor Christus", + "na Christus" + ], + "ERAS": [ + "v.Chr.", + "n.Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januari", diff --git a/src/ngLocale/angular-locale_nl-sr.js b/src/ngLocale/angular-locale_nl-sr.js index 9636fa64e3fb..aeb311f38519 100644 --- a/src/ngLocale/angular-locale_nl-sr.js +++ b/src/ngLocale/angular-locale_nl-sr.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vrijdag", "zaterdag" ], + "ERANAMES": [ + "voor Christus", + "na Christus" + ], + "ERAS": [ + "v.Chr.", + "n.Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januari", diff --git a/src/ngLocale/angular-locale_nl-sx.js b/src/ngLocale/angular-locale_nl-sx.js index bd907b2ddc87..94ccec8ac9da 100644 --- a/src/ngLocale/angular-locale_nl-sx.js +++ b/src/ngLocale/angular-locale_nl-sx.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vrijdag", "zaterdag" ], + "ERANAMES": [ + "voor Christus", + "na Christus" + ], + "ERAS": [ + "v.Chr.", + "n.Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januari", diff --git a/src/ngLocale/angular-locale_nl.js b/src/ngLocale/angular-locale_nl.js index 18bf120ed631..5e2cd5b346e8 100644 --- a/src/ngLocale/angular-locale_nl.js +++ b/src/ngLocale/angular-locale_nl.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vrijdag", "zaterdag" ], + "ERANAMES": [ + "voor Christus", + "na Christus" + ], + "ERAS": [ + "v.Chr.", + "n.Chr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januari", diff --git a/src/ngLocale/angular-locale_nmg-cm.js b/src/ngLocale/angular-locale_nmg-cm.js index 34839408d644..24594190e8da 100644 --- a/src/ngLocale/angular-locale_nmg-cm.js +++ b/src/ngLocale/angular-locale_nmg-cm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "mab\u00e1g\u00e1 m\u00e1 sukul", "s\u00e1sadi" ], + "ERANAMES": [ + "B\u00f3 Lahl\u025b\u0304", + "Pfi\u025b Bur\u012b" + ], + "ERAS": [ + "BL", + "PB" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "ngw\u025bn mat\u00e1hra", diff --git a/src/ngLocale/angular-locale_nmg.js b/src/ngLocale/angular-locale_nmg.js index de4ac50bfe77..98f5073e6f78 100644 --- a/src/ngLocale/angular-locale_nmg.js +++ b/src/ngLocale/angular-locale_nmg.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "mab\u00e1g\u00e1 m\u00e1 sukul", "s\u00e1sadi" ], + "ERANAMES": [ + "B\u00f3 Lahl\u025b\u0304", + "Pfi\u025b Bur\u012b" + ], + "ERAS": [ + "BL", + "PB" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "ngw\u025bn mat\u00e1hra", diff --git a/src/ngLocale/angular-locale_nn-no.js b/src/ngLocale/angular-locale_nn-no.js index f52c618df35d..c303718bb475 100644 --- a/src/ngLocale/angular-locale_nn-no.js +++ b/src/ngLocale/angular-locale_nn-no.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "fredag", "laurdag" ], + "ERANAMES": [ + "f.Kr.", + "e.Kr." + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_nn.js b/src/ngLocale/angular-locale_nn.js index 271c47a86aa0..6d2f0370c59a 100644 --- a/src/ngLocale/angular-locale_nn.js +++ b/src/ngLocale/angular-locale_nn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "fredag", "laurdag" ], + "ERANAMES": [ + "f.Kr.", + "e.Kr." + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_nnh-cm.js b/src/ngLocale/angular-locale_nnh-cm.js index 36d5b79f4790..b982922d442e 100644 --- a/src/ngLocale/angular-locale_nnh-cm.js +++ b/src/ngLocale/angular-locale_nnh-cm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "mvf\u00f2 m\u00e0ga ly\u025b\u030c\u02bc", "m\u00e0ga ly\u025b\u030c\u02bc" ], + "ERANAMES": [ + "m\u00e9 zy\u00e9 Y\u011bs\u00f4", + "m\u00e9 g\u00ffo \u0144zy\u00e9 Y\u011bs\u00f4" + ], + "ERAS": [ + "m.z.Y.", + "m.g.n.Y." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "sa\u014b tsets\u025b\u0300\u025b l\u00f9m", diff --git a/src/ngLocale/angular-locale_nnh.js b/src/ngLocale/angular-locale_nnh.js index 31d7b9703272..878777c17483 100644 --- a/src/ngLocale/angular-locale_nnh.js +++ b/src/ngLocale/angular-locale_nnh.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "mvf\u00f2 m\u00e0ga ly\u025b\u030c\u02bc", "m\u00e0ga ly\u025b\u030c\u02bc" ], + "ERANAMES": [ + "m\u00e9 zy\u00e9 Y\u011bs\u00f4", + "m\u00e9 g\u00ffo \u0144zy\u00e9 Y\u011bs\u00f4" + ], + "ERAS": [ + "m.z.Y.", + "m.g.n.Y." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "sa\u014b tsets\u025b\u0300\u025b l\u00f9m", diff --git a/src/ngLocale/angular-locale_no-no.js b/src/ngLocale/angular-locale_no-no.js index ce8918967410..45211e30761a 100644 --- a/src/ngLocale/angular-locale_no-no.js +++ b/src/ngLocale/angular-locale_no-no.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "fredag", "l\u00f8rdag" ], + "ERANAMES": [ + "f.Kr.", + "e.Kr." + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_no.js b/src/ngLocale/angular-locale_no.js index 8e121fb8e522..8348cabdbabd 100644 --- a/src/ngLocale/angular-locale_no.js +++ b/src/ngLocale/angular-locale_no.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "fredag", "l\u00f8rdag" ], + "ERANAMES": [ + "f.Kr.", + "e.Kr." + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_nr-za.js b/src/ngLocale/angular-locale_nr-za.js index 4233055f33f2..60a2745ff3b3 100644 --- a/src/ngLocale/angular-locale_nr-za.js +++ b/src/ngLocale/angular-locale_nr-za.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "ngoLesihlanu", "umGqibelo" ], + "ERANAMES": [ + "BC", + "AD" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Janabari", diff --git a/src/ngLocale/angular-locale_nr.js b/src/ngLocale/angular-locale_nr.js index d856511d9084..daa76c0aeca4 100644 --- a/src/ngLocale/angular-locale_nr.js +++ b/src/ngLocale/angular-locale_nr.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "ngoLesihlanu", "umGqibelo" ], + "ERANAMES": [ + "BC", + "AD" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Janabari", diff --git a/src/ngLocale/angular-locale_nso-za.js b/src/ngLocale/angular-locale_nso-za.js index 3038e598fdc8..493ec38ee8a0 100644 --- a/src/ngLocale/angular-locale_nso-za.js +++ b/src/ngLocale/angular-locale_nso-za.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Labohlano", "Mokibelo" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Janaware", diff --git a/src/ngLocale/angular-locale_nso.js b/src/ngLocale/angular-locale_nso.js index 5a28605cbbb1..50d5663a4a57 100644 --- a/src/ngLocale/angular-locale_nso.js +++ b/src/ngLocale/angular-locale_nso.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Labohlano", "Mokibelo" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Janaware", diff --git a/src/ngLocale/angular-locale_nus-sd.js b/src/ngLocale/angular-locale_nus-sd.js index d010c4c578a3..c28169b818d8 100644 --- a/src/ngLocale/angular-locale_nus-sd.js +++ b/src/ngLocale/angular-locale_nus-sd.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Dhieec l\u00e4tni", "B\u00e4k\u025bl l\u00e4tni" ], + "ERANAMES": [ + "A ka\u0331n Yecu ni dap", + "\u0190 ca Yecu dap" + ], + "ERAS": [ + "AY", + "\u0190Y" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Tiop thar p\u025bt", diff --git a/src/ngLocale/angular-locale_nus.js b/src/ngLocale/angular-locale_nus.js index 53b3e950a827..244e906db193 100644 --- a/src/ngLocale/angular-locale_nus.js +++ b/src/ngLocale/angular-locale_nus.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Dhieec l\u00e4tni", "B\u00e4k\u025bl l\u00e4tni" ], + "ERANAMES": [ + "A ka\u0331n Yecu ni dap", + "\u0190 ca Yecu dap" + ], + "ERAS": [ + "AY", + "\u0190Y" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Tiop thar p\u025bt", diff --git a/src/ngLocale/angular-locale_nyn-ug.js b/src/ngLocale/angular-locale_nyn-ug.js index a7c452cc89e4..d36936a1bcac 100644 --- a/src/ngLocale/angular-locale_nyn-ug.js +++ b/src/ngLocale/angular-locale_nyn-ug.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Orwakataano", "Orwamukaaga" ], + "ERANAMES": [ + "Kurisito Atakaijire", + "Kurisito Yaijire" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Okwokubanza", diff --git a/src/ngLocale/angular-locale_nyn.js b/src/ngLocale/angular-locale_nyn.js index d30123a4bbca..c76061e7f398 100644 --- a/src/ngLocale/angular-locale_nyn.js +++ b/src/ngLocale/angular-locale_nyn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Orwakataano", "Orwamukaaga" ], + "ERANAMES": [ + "Kurisito Atakaijire", + "Kurisito Yaijire" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Okwokubanza", diff --git a/src/ngLocale/angular-locale_om-et.js b/src/ngLocale/angular-locale_om-et.js index 5c3b6cd2134d..d3e129ee1760 100644 --- a/src/ngLocale/angular-locale_om-et.js +++ b/src/ngLocale/angular-locale_om-et.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jimaata", "Sanbata" ], + "ERANAMES": [ + "KD", + "KB" + ], + "ERAS": [ + "KD", + "KB" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Amajjii", diff --git a/src/ngLocale/angular-locale_om-ke.js b/src/ngLocale/angular-locale_om-ke.js index 5ec54e596964..2e65a8fd09ee 100644 --- a/src/ngLocale/angular-locale_om-ke.js +++ b/src/ngLocale/angular-locale_om-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jimaata", "Sanbata" ], + "ERANAMES": [ + "KD", + "KB" + ], + "ERAS": [ + "KD", + "KB" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Amajjii", diff --git a/src/ngLocale/angular-locale_om.js b/src/ngLocale/angular-locale_om.js index ad7e8dbd2e70..8b95f8cb8b82 100644 --- a/src/ngLocale/angular-locale_om.js +++ b/src/ngLocale/angular-locale_om.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jimaata", "Sanbata" ], + "ERANAMES": [ + "KD", + "KB" + ], + "ERAS": [ + "KD", + "KB" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Amajjii", diff --git a/src/ngLocale/angular-locale_or-in.js b/src/ngLocale/angular-locale_or-in.js index 8b76f8a00d06..4f36a046c91c 100644 --- a/src/ngLocale/angular-locale_or-in.js +++ b/src/ngLocale/angular-locale_or-in.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0b36\u0b41\u0b15\u0b4d\u0b30\u0b2c\u0b3e\u0b30", "\u0b36\u0b28\u0b3f\u0b2c\u0b3e\u0b30" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0b1c\u0b3e\u0b28\u0b41\u0b06\u0b30\u0b40", diff --git a/src/ngLocale/angular-locale_or.js b/src/ngLocale/angular-locale_or.js index 6f930e42e1e7..a93160bd5401 100644 --- a/src/ngLocale/angular-locale_or.js +++ b/src/ngLocale/angular-locale_or.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0b36\u0b41\u0b15\u0b4d\u0b30\u0b2c\u0b3e\u0b30", "\u0b36\u0b28\u0b3f\u0b2c\u0b3e\u0b30" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0b1c\u0b3e\u0b28\u0b41\u0b06\u0b30\u0b40", diff --git a/src/ngLocale/angular-locale_os-ge.js b/src/ngLocale/angular-locale_os-ge.js index d7ca239681ba..d27c556cb2e9 100644 --- a/src/ngLocale/angular-locale_os-ge.js +++ b/src/ngLocale/angular-locale_os-ge.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043c\u0430\u0439\u0440\u04d5\u043c\u0431\u043e\u043d", "\u0441\u0430\u0431\u0430\u0442" ], + "ERANAMES": [ + "\u043d.\u0434.\u0430.", + "\u043d.\u0434." + ], + "ERAS": [ + "\u043d.\u0434.\u0430.", + "\u043d.\u0434." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u044f\u043d\u0432\u0430\u0440\u044b", diff --git a/src/ngLocale/angular-locale_os-ru.js b/src/ngLocale/angular-locale_os-ru.js index 01998baa6bdf..f5ed18454b30 100644 --- a/src/ngLocale/angular-locale_os-ru.js +++ b/src/ngLocale/angular-locale_os-ru.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043c\u0430\u0439\u0440\u04d5\u043c\u0431\u043e\u043d", "\u0441\u0430\u0431\u0430\u0442" ], + "ERANAMES": [ + "\u043d.\u0434.\u0430.", + "\u043d.\u0434." + ], + "ERAS": [ + "\u043d.\u0434.\u0430.", + "\u043d.\u0434." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u044f\u043d\u0432\u0430\u0440\u044b", diff --git a/src/ngLocale/angular-locale_os.js b/src/ngLocale/angular-locale_os.js index baebdb10514b..66fbdbc9eb6f 100644 --- a/src/ngLocale/angular-locale_os.js +++ b/src/ngLocale/angular-locale_os.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043c\u0430\u0439\u0440\u04d5\u043c\u0431\u043e\u043d", "\u0441\u0430\u0431\u0430\u0442" ], + "ERANAMES": [ + "\u043d.\u0434.\u0430.", + "\u043d.\u0434." + ], + "ERAS": [ + "\u043d.\u0434.\u0430.", + "\u043d.\u0434." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u044f\u043d\u0432\u0430\u0440\u044b", diff --git a/src/ngLocale/angular-locale_pa-arab-pk.js b/src/ngLocale/angular-locale_pa-arab-pk.js index 1e92ced1a819..0e85f68ca48d 100644 --- a/src/ngLocale/angular-locale_pa-arab-pk.js +++ b/src/ngLocale/angular-locale_pa-arab-pk.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u062c\u0645\u0639\u06c1", "\u06c1\u0641\u062a\u06c1" ], + "ERANAMES": [ + "\u0627\u064a\u0633\u0627\u067e\u0648\u0631\u0648", + "\u0633\u06ba" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u062c\u0646\u0648\u0631\u06cc", diff --git a/src/ngLocale/angular-locale_pa-arab.js b/src/ngLocale/angular-locale_pa-arab.js index 37707621ed02..d0f46e5dc0d9 100644 --- a/src/ngLocale/angular-locale_pa-arab.js +++ b/src/ngLocale/angular-locale_pa-arab.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u062c\u0645\u0639\u06c1", "\u06c1\u0641\u062a\u06c1" ], + "ERANAMES": [ + "\u0627\u064a\u0633\u0627\u067e\u0648\u0631\u0648", + "\u0633\u06ba" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u062c\u0646\u0648\u0631\u06cc", diff --git a/src/ngLocale/angular-locale_pa-guru-in.js b/src/ngLocale/angular-locale_pa-guru-in.js index 13b8b0392250..7afe7450d324 100644 --- a/src/ngLocale/angular-locale_pa-guru-in.js +++ b/src/ngLocale/angular-locale_pa-guru-in.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0a38\u0a3c\u0a41\u0a71\u0a15\u0a30\u0a35\u0a3e\u0a30", "\u0a38\u0a3c\u0a28\u0a3f\u0a71\u0a1a\u0a30\u0a35\u0a3e\u0a30" ], + "ERANAMES": [ + "\u0a08\u0a38\u0a35\u0a40 \u0a2a\u0a42\u0a30\u0a35", + "\u0a08\u0a38\u0a35\u0a40 \u0a38\u0a70\u0a28" + ], + "ERAS": [ + "\u0a08. \u0a2a\u0a42.", + "\u0a38\u0a70\u0a28" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0a1c\u0a28\u0a35\u0a30\u0a40", diff --git a/src/ngLocale/angular-locale_pa-guru.js b/src/ngLocale/angular-locale_pa-guru.js index 6a016bcee484..f647501e914c 100644 --- a/src/ngLocale/angular-locale_pa-guru.js +++ b/src/ngLocale/angular-locale_pa-guru.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0a38\u0a3c\u0a41\u0a71\u0a15\u0a30\u0a35\u0a3e\u0a30", "\u0a38\u0a3c\u0a28\u0a3f\u0a71\u0a1a\u0a30\u0a35\u0a3e\u0a30" ], + "ERANAMES": [ + "\u0a08\u0a38\u0a35\u0a40 \u0a2a\u0a42\u0a30\u0a35", + "\u0a08\u0a38\u0a35\u0a40 \u0a38\u0a70\u0a28" + ], + "ERAS": [ + "\u0a08. \u0a2a\u0a42.", + "\u0a38\u0a70\u0a28" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0a1c\u0a28\u0a35\u0a30\u0a40", diff --git a/src/ngLocale/angular-locale_pa.js b/src/ngLocale/angular-locale_pa.js index 3579a4a6f9df..71090816a4c8 100644 --- a/src/ngLocale/angular-locale_pa.js +++ b/src/ngLocale/angular-locale_pa.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0a38\u0a3c\u0a41\u0a71\u0a15\u0a30\u0a35\u0a3e\u0a30", "\u0a38\u0a3c\u0a28\u0a3f\u0a71\u0a1a\u0a30\u0a35\u0a3e\u0a30" ], + "ERANAMES": [ + "\u0a08\u0a38\u0a35\u0a40 \u0a2a\u0a42\u0a30\u0a35", + "\u0a08\u0a38\u0a35\u0a40 \u0a38\u0a70\u0a28" + ], + "ERAS": [ + "\u0a08. \u0a2a\u0a42.", + "\u0a38\u0a70\u0a28" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0a1c\u0a28\u0a35\u0a30\u0a40", diff --git a/src/ngLocale/angular-locale_pl-pl.js b/src/ngLocale/angular-locale_pl-pl.js index 56ed3ea46aaa..c25f6f728cfd 100644 --- a/src/ngLocale/angular-locale_pl-pl.js +++ b/src/ngLocale/angular-locale_pl-pl.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "pi\u0105tek", "sobota" ], + "ERANAMES": [ + "p.n.e.", + "n.e." + ], + "ERAS": [ + "p.n.e.", + "n.e." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "stycznia", diff --git a/src/ngLocale/angular-locale_pl.js b/src/ngLocale/angular-locale_pl.js index 667b822a968b..af8d76be6add 100644 --- a/src/ngLocale/angular-locale_pl.js +++ b/src/ngLocale/angular-locale_pl.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "pi\u0105tek", "sobota" ], + "ERANAMES": [ + "p.n.e.", + "n.e." + ], + "ERAS": [ + "p.n.e.", + "n.e." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "stycznia", diff --git a/src/ngLocale/angular-locale_ps-af.js b/src/ngLocale/angular-locale_ps-af.js index 4d7dda779e8e..d6d407750223 100644 --- a/src/ngLocale/angular-locale_ps-af.js +++ b/src/ngLocale/angular-locale_ps-af.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u062c\u0645\u0639\u0647", "\u0634\u0646\u0628\u0647" ], + "ERANAMES": [ + "\u0642.\u0645.", + "\u0645." + ], + "ERAS": [ + "\u0642.\u0645.", + "\u0645." + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u062c\u0646\u0648\u0631\u064a", diff --git a/src/ngLocale/angular-locale_ps.js b/src/ngLocale/angular-locale_ps.js index 8fd1aff98f8b..4bbe51110495 100644 --- a/src/ngLocale/angular-locale_ps.js +++ b/src/ngLocale/angular-locale_ps.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u062c\u0645\u0639\u0647", "\u0634\u0646\u0628\u0647" ], + "ERANAMES": [ + "\u0642.\u0645.", + "\u0645." + ], + "ERAS": [ + "\u0642.\u0645.", + "\u0645." + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u062c\u0646\u0648\u0631\u064a", diff --git a/src/ngLocale/angular-locale_pt-ao.js b/src/ngLocale/angular-locale_pt-ao.js index 6cc68dc12a91..dcc91dab62aa 100644 --- a/src/ngLocale/angular-locale_pt-ao.js +++ b/src/ngLocale/angular-locale_pt-ao.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "sexta-feira", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "depois de Cristo" + ], + "ERAS": [ + "a.C.", + "d.C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janeiro", diff --git a/src/ngLocale/angular-locale_pt-br.js b/src/ngLocale/angular-locale_pt-br.js index 2a82974b1450..cd86e06355a2 100644 --- a/src/ngLocale/angular-locale_pt-br.js +++ b/src/ngLocale/angular-locale_pt-br.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "sexta-feira", "s\u00e1bado" ], + "ERANAMES": [ + "Antes de Cristo", + "Ano do Senhor" + ], + "ERAS": [ + "a.C.", + "d.C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "janeiro", diff --git a/src/ngLocale/angular-locale_pt-cv.js b/src/ngLocale/angular-locale_pt-cv.js index 689c1c1a3f6f..d9beaa1d60b9 100644 --- a/src/ngLocale/angular-locale_pt-cv.js +++ b/src/ngLocale/angular-locale_pt-cv.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "sexta-feira", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "depois de Cristo" + ], + "ERAS": [ + "a.C.", + "d.C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janeiro", diff --git a/src/ngLocale/angular-locale_pt-gw.js b/src/ngLocale/angular-locale_pt-gw.js index 36953b455c8f..801f3e72ca9d 100644 --- a/src/ngLocale/angular-locale_pt-gw.js +++ b/src/ngLocale/angular-locale_pt-gw.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "sexta-feira", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "depois de Cristo" + ], + "ERAS": [ + "a.C.", + "d.C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janeiro", diff --git a/src/ngLocale/angular-locale_pt-mo.js b/src/ngLocale/angular-locale_pt-mo.js index 6b89e92fe48f..fecce7cb9315 100644 --- a/src/ngLocale/angular-locale_pt-mo.js +++ b/src/ngLocale/angular-locale_pt-mo.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "sexta-feira", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "depois de Cristo" + ], + "ERAS": [ + "a.C.", + "d.C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "janeiro", diff --git a/src/ngLocale/angular-locale_pt-mz.js b/src/ngLocale/angular-locale_pt-mz.js index 4fbaa46ea7f2..e7450a218675 100644 --- a/src/ngLocale/angular-locale_pt-mz.js +++ b/src/ngLocale/angular-locale_pt-mz.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "sexta-feira", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "depois de Cristo" + ], + "ERAS": [ + "a.C.", + "d.C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "janeiro", diff --git a/src/ngLocale/angular-locale_pt-pt.js b/src/ngLocale/angular-locale_pt-pt.js index f259c39ebc86..6718f9dc26d1 100644 --- a/src/ngLocale/angular-locale_pt-pt.js +++ b/src/ngLocale/angular-locale_pt-pt.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "sexta-feira", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "depois de Cristo" + ], + "ERAS": [ + "a.C.", + "d.C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janeiro", diff --git a/src/ngLocale/angular-locale_pt-st.js b/src/ngLocale/angular-locale_pt-st.js index 6d5b372d2eef..a6ff9cd7c0b1 100644 --- a/src/ngLocale/angular-locale_pt-st.js +++ b/src/ngLocale/angular-locale_pt-st.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "sexta-feira", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "depois de Cristo" + ], + "ERAS": [ + "a.C.", + "d.C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janeiro", diff --git a/src/ngLocale/angular-locale_pt-tl.js b/src/ngLocale/angular-locale_pt-tl.js index 51f1cda87334..bb36d6dc8e37 100644 --- a/src/ngLocale/angular-locale_pt-tl.js +++ b/src/ngLocale/angular-locale_pt-tl.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "sexta-feira", "s\u00e1bado" ], + "ERANAMES": [ + "antes de Cristo", + "depois de Cristo" + ], + "ERAS": [ + "a.C.", + "d.C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janeiro", diff --git a/src/ngLocale/angular-locale_pt.js b/src/ngLocale/angular-locale_pt.js index 4bb9b024ac27..72366db7e9ae 100644 --- a/src/ngLocale/angular-locale_pt.js +++ b/src/ngLocale/angular-locale_pt.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "sexta-feira", "s\u00e1bado" ], + "ERANAMES": [ + "Antes de Cristo", + "Ano do Senhor" + ], + "ERAS": [ + "a.C.", + "d.C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "janeiro", diff --git a/src/ngLocale/angular-locale_qu-bo.js b/src/ngLocale/angular-locale_qu-bo.js index 5f866ab8cf95..3888066614f5 100644 --- a/src/ngLocale/angular-locale_qu-bo.js +++ b/src/ngLocale/angular-locale_qu-bo.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Viernes", "S\u00e1bado" ], + "ERANAMES": [ + "BCE", + "d.C." + ], + "ERAS": [ + "BCE", + "d.C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Qulla puquy", diff --git a/src/ngLocale/angular-locale_qu-ec.js b/src/ngLocale/angular-locale_qu-ec.js index c458431303f3..16b5a5cee512 100644 --- a/src/ngLocale/angular-locale_qu-ec.js +++ b/src/ngLocale/angular-locale_qu-ec.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Viernes", "S\u00e1bado" ], + "ERANAMES": [ + "BCE", + "d.C." + ], + "ERAS": [ + "BCE", + "d.C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Qulla puquy", diff --git a/src/ngLocale/angular-locale_qu-pe.js b/src/ngLocale/angular-locale_qu-pe.js index 5586c8e3c5ab..dd1e03ee34bb 100644 --- a/src/ngLocale/angular-locale_qu-pe.js +++ b/src/ngLocale/angular-locale_qu-pe.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Viernes", "S\u00e1bado" ], + "ERANAMES": [ + "BCE", + "d.C." + ], + "ERAS": [ + "BCE", + "d.C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Qulla puquy", diff --git a/src/ngLocale/angular-locale_qu.js b/src/ngLocale/angular-locale_qu.js index b02fada5afb4..d5f7873202c5 100644 --- a/src/ngLocale/angular-locale_qu.js +++ b/src/ngLocale/angular-locale_qu.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Viernes", "S\u00e1bado" ], + "ERANAMES": [ + "BCE", + "d.C." + ], + "ERAS": [ + "BCE", + "d.C." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Qulla puquy", diff --git a/src/ngLocale/angular-locale_rm-ch.js b/src/ngLocale/angular-locale_rm-ch.js index 94771b02ea7c..091c0827e2fb 100644 --- a/src/ngLocale/angular-locale_rm-ch.js +++ b/src/ngLocale/angular-locale_rm-ch.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "venderdi", "sonda" ], + "ERANAMES": [ + "avant Cristus", + "suenter Cristus" + ], + "ERAS": [ + "av. Cr.", + "s. Cr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "schaner", diff --git a/src/ngLocale/angular-locale_rm.js b/src/ngLocale/angular-locale_rm.js index 0ea12f098410..7bddcf97216e 100644 --- a/src/ngLocale/angular-locale_rm.js +++ b/src/ngLocale/angular-locale_rm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "venderdi", "sonda" ], + "ERANAMES": [ + "avant Cristus", + "suenter Cristus" + ], + "ERAS": [ + "av. Cr.", + "s. Cr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "schaner", diff --git a/src/ngLocale/angular-locale_rn-bi.js b/src/ngLocale/angular-locale_rn-bi.js index fb1f58fdb769..cd61a1d476df 100644 --- a/src/ngLocale/angular-locale_rn-bi.js +++ b/src/ngLocale/angular-locale_rn-bi.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ku wa gatanu", "Ku wa gatandatu" ], + "ERANAMES": [ + "Mbere ya Yezu", + "Nyuma ya Yezu" + ], + "ERAS": [ + "Mb.Y.", + "Ny.Y" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Nzero", diff --git a/src/ngLocale/angular-locale_rn.js b/src/ngLocale/angular-locale_rn.js index 5f5864c726ca..0a2a5e8ec88d 100644 --- a/src/ngLocale/angular-locale_rn.js +++ b/src/ngLocale/angular-locale_rn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ku wa gatanu", "Ku wa gatandatu" ], + "ERANAMES": [ + "Mbere ya Yezu", + "Nyuma ya Yezu" + ], + "ERAS": [ + "Mb.Y.", + "Ny.Y" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Nzero", diff --git a/src/ngLocale/angular-locale_ro-md.js b/src/ngLocale/angular-locale_ro-md.js index a24bbd42f144..b36304708566 100644 --- a/src/ngLocale/angular-locale_ro-md.js +++ b/src/ngLocale/angular-locale_ro-md.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vineri", "s\u00e2mb\u0103t\u0103" ], + "ERANAMES": [ + "\u00eenainte de Hristos", + "dup\u0103 Hristos" + ], + "ERAS": [ + "\u00ee.Hr.", + "d.Hr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "ianuarie", diff --git a/src/ngLocale/angular-locale_ro-ro.js b/src/ngLocale/angular-locale_ro-ro.js index 9e70cacbbaa3..d87922602678 100644 --- a/src/ngLocale/angular-locale_ro-ro.js +++ b/src/ngLocale/angular-locale_ro-ro.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vineri", "s\u00e2mb\u0103t\u0103" ], + "ERANAMES": [ + "\u00eenainte de Hristos", + "dup\u0103 Hristos" + ], + "ERAS": [ + "\u00ee.Hr.", + "d.Hr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "ianuarie", diff --git a/src/ngLocale/angular-locale_ro.js b/src/ngLocale/angular-locale_ro.js index 9c2c32e87caf..3c52dd2a70d1 100644 --- a/src/ngLocale/angular-locale_ro.js +++ b/src/ngLocale/angular-locale_ro.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "vineri", "s\u00e2mb\u0103t\u0103" ], + "ERANAMES": [ + "\u00eenainte de Hristos", + "dup\u0103 Hristos" + ], + "ERAS": [ + "\u00ee.Hr.", + "d.Hr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "ianuarie", diff --git a/src/ngLocale/angular-locale_rof-tz.js b/src/ngLocale/angular-locale_rof-tz.js index 273d55976466..caf167ad1126 100644 --- a/src/ngLocale/angular-locale_rof-tz.js +++ b/src/ngLocale/angular-locale_rof-tz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Ijumamosi" ], + "ERANAMES": [ + "Kabla ya Mayesu", + "Baada ya Mayesu" + ], + "ERAS": [ + "KM", + "BM" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mweri wa kwanza", diff --git a/src/ngLocale/angular-locale_rof.js b/src/ngLocale/angular-locale_rof.js index 4443fe578d58..13a90e835fbd 100644 --- a/src/ngLocale/angular-locale_rof.js +++ b/src/ngLocale/angular-locale_rof.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Ijumamosi" ], + "ERANAMES": [ + "Kabla ya Mayesu", + "Baada ya Mayesu" + ], + "ERAS": [ + "KM", + "BM" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mweri wa kwanza", diff --git a/src/ngLocale/angular-locale_ru-by.js b/src/ngLocale/angular-locale_ru-by.js index 00c71fd1829a..f735266cf0e2 100644 --- a/src/ngLocale/angular-locale_ru-by.js +++ b/src/ngLocale/angular-locale_ru-by.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u044f\u0442\u043d\u0438\u0446\u0430", "\u0441\u0443\u0431\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u0434\u043e \u043d. \u044d.", + "\u043d. \u044d." + ], + "ERAS": [ + "\u0434\u043e \u043d. \u044d.", + "\u043d. \u044d." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u044f\u043d\u0432\u0430\u0440\u044f", diff --git a/src/ngLocale/angular-locale_ru-kg.js b/src/ngLocale/angular-locale_ru-kg.js index f4e8e06cbd28..b1d9db982035 100644 --- a/src/ngLocale/angular-locale_ru-kg.js +++ b/src/ngLocale/angular-locale_ru-kg.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u044f\u0442\u043d\u0438\u0446\u0430", "\u0441\u0443\u0431\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u0434\u043e \u043d. \u044d.", + "\u043d. \u044d." + ], + "ERAS": [ + "\u0434\u043e \u043d. \u044d.", + "\u043d. \u044d." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u044f\u043d\u0432\u0430\u0440\u044f", diff --git a/src/ngLocale/angular-locale_ru-kz.js b/src/ngLocale/angular-locale_ru-kz.js index 2c277420ccd9..a1c93672969d 100644 --- a/src/ngLocale/angular-locale_ru-kz.js +++ b/src/ngLocale/angular-locale_ru-kz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u044f\u0442\u043d\u0438\u0446\u0430", "\u0441\u0443\u0431\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u0434\u043e \u043d. \u044d.", + "\u043d. \u044d." + ], + "ERAS": [ + "\u0434\u043e \u043d. \u044d.", + "\u043d. \u044d." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u044f\u043d\u0432\u0430\u0440\u044f", diff --git a/src/ngLocale/angular-locale_ru-md.js b/src/ngLocale/angular-locale_ru-md.js index a04a31b9fff0..de3f0498624d 100644 --- a/src/ngLocale/angular-locale_ru-md.js +++ b/src/ngLocale/angular-locale_ru-md.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u044f\u0442\u043d\u0438\u0446\u0430", "\u0441\u0443\u0431\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u0434\u043e \u043d. \u044d.", + "\u043d. \u044d." + ], + "ERAS": [ + "\u0434\u043e \u043d. \u044d.", + "\u043d. \u044d." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u044f\u043d\u0432\u0430\u0440\u044f", diff --git a/src/ngLocale/angular-locale_ru-ru.js b/src/ngLocale/angular-locale_ru-ru.js index eb4084f8dc1d..e9337210de25 100644 --- a/src/ngLocale/angular-locale_ru-ru.js +++ b/src/ngLocale/angular-locale_ru-ru.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u044f\u0442\u043d\u0438\u0446\u0430", "\u0441\u0443\u0431\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u0434\u043e \u043d. \u044d.", + "\u043d. \u044d." + ], + "ERAS": [ + "\u0434\u043e \u043d. \u044d.", + "\u043d. \u044d." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u044f\u043d\u0432\u0430\u0440\u044f", diff --git a/src/ngLocale/angular-locale_ru-ua.js b/src/ngLocale/angular-locale_ru-ua.js index 66030448a331..1badc1b2075f 100644 --- a/src/ngLocale/angular-locale_ru-ua.js +++ b/src/ngLocale/angular-locale_ru-ua.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u044f\u0442\u043d\u0438\u0446\u0430", "\u0441\u0443\u0431\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u0434\u043e \u043d. \u044d.", + "\u043d. \u044d." + ], + "ERAS": [ + "\u0434\u043e \u043d. \u044d.", + "\u043d. \u044d." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u044f\u043d\u0432\u0430\u0440\u044f", diff --git a/src/ngLocale/angular-locale_ru.js b/src/ngLocale/angular-locale_ru.js index 08c04d9b26b8..553360f025fc 100644 --- a/src/ngLocale/angular-locale_ru.js +++ b/src/ngLocale/angular-locale_ru.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u044f\u0442\u043d\u0438\u0446\u0430", "\u0441\u0443\u0431\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u0434\u043e \u043d. \u044d.", + "\u043d. \u044d." + ], + "ERAS": [ + "\u0434\u043e \u043d. \u044d.", + "\u043d. \u044d." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u044f\u043d\u0432\u0430\u0440\u044f", diff --git a/src/ngLocale/angular-locale_rw-rw.js b/src/ngLocale/angular-locale_rw-rw.js index ba7ec07af37f..72a4210be621 100644 --- a/src/ngLocale/angular-locale_rw-rw.js +++ b/src/ngLocale/angular-locale_rw-rw.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Kuwa gatanu", "Kuwa gatandatu" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mutarama", diff --git a/src/ngLocale/angular-locale_rw.js b/src/ngLocale/angular-locale_rw.js index bacbb4c4ad91..3671e63e42a9 100644 --- a/src/ngLocale/angular-locale_rw.js +++ b/src/ngLocale/angular-locale_rw.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Kuwa gatanu", "Kuwa gatandatu" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mutarama", diff --git a/src/ngLocale/angular-locale_rwk-tz.js b/src/ngLocale/angular-locale_rwk-tz.js index 5990ef89c1bc..3dcb29aea7dc 100644 --- a/src/ngLocale/angular-locale_rwk-tz.js +++ b/src/ngLocale/angular-locale_rwk-tz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Kabla ya Kristu", + "Baada ya Kristu" + ], + "ERAS": [ + "KK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_rwk.js b/src/ngLocale/angular-locale_rwk.js index 63770fb4e4ae..726ed59ad231 100644 --- a/src/ngLocale/angular-locale_rwk.js +++ b/src/ngLocale/angular-locale_rwk.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Kabla ya Kristu", + "Baada ya Kristu" + ], + "ERAS": [ + "KK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_sah-ru.js b/src/ngLocale/angular-locale_sah-ru.js index b9efb1c60376..197cb9df42b3 100644 --- a/src/ngLocale/angular-locale_sah-ru.js +++ b/src/ngLocale/angular-locale_sah-ru.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0411\u044d\u044d\u0442\u0438\u04a5\u0441\u044d", "\u0421\u0443\u0431\u0443\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u0431. \u044d. \u0438.", + "\u0431. \u044d" + ], + "ERAS": [ + "\u0431. \u044d. \u0438.", + "\u0431. \u044d" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0422\u043e\u0445\u0441\u0443\u043d\u043d\u044c\u0443", diff --git a/src/ngLocale/angular-locale_sah.js b/src/ngLocale/angular-locale_sah.js index 234f3c41e4b2..55a33df6e4e4 100644 --- a/src/ngLocale/angular-locale_sah.js +++ b/src/ngLocale/angular-locale_sah.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0411\u044d\u044d\u0442\u0438\u04a5\u0441\u044d", "\u0421\u0443\u0431\u0443\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u0431. \u044d. \u0438.", + "\u0431. \u044d" + ], + "ERAS": [ + "\u0431. \u044d. \u0438.", + "\u0431. \u044d" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0422\u043e\u0445\u0441\u0443\u043d\u043d\u044c\u0443", diff --git a/src/ngLocale/angular-locale_saq-ke.js b/src/ngLocale/angular-locale_saq-ke.js index e3b030881523..16d6bb8041b2 100644 --- a/src/ngLocale/angular-locale_saq-ke.js +++ b/src/ngLocale/angular-locale_saq-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Mderot ee sapa", "Mderot ee kwe" ], + "ERANAMES": [ + "Kabla ya Christo", + "Baada ya Christo" + ], + "ERAS": [ + "KK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Lapa le obo", diff --git a/src/ngLocale/angular-locale_saq.js b/src/ngLocale/angular-locale_saq.js index 6b23b0de995b..728de53bc17c 100644 --- a/src/ngLocale/angular-locale_saq.js +++ b/src/ngLocale/angular-locale_saq.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Mderot ee sapa", "Mderot ee kwe" ], + "ERANAMES": [ + "Kabla ya Christo", + "Baada ya Christo" + ], + "ERAS": [ + "KK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Lapa le obo", diff --git a/src/ngLocale/angular-locale_sbp-tz.js b/src/ngLocale/angular-locale_sbp-tz.js index 819f70d0c476..1e5a0e825c40 100644 --- a/src/ngLocale/angular-locale_sbp-tz.js +++ b/src/ngLocale/angular-locale_sbp-tz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Ashanali uKilisito", + "Pamwandi ya Kilisto" + ], + "ERAS": [ + "AK", + "PK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mupalangulwa", diff --git a/src/ngLocale/angular-locale_sbp.js b/src/ngLocale/angular-locale_sbp.js index 509b0bdb2a70..da6106a6a81a 100644 --- a/src/ngLocale/angular-locale_sbp.js +++ b/src/ngLocale/angular-locale_sbp.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Ashanali uKilisito", + "Pamwandi ya Kilisto" + ], + "ERAS": [ + "AK", + "PK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Mupalangulwa", diff --git a/src/ngLocale/angular-locale_se-fi.js b/src/ngLocale/angular-locale_se-fi.js index 970f0d3ec7c9..62de6b1ada6b 100644 --- a/src/ngLocale/angular-locale_se-fi.js +++ b/src/ngLocale/angular-locale_se-fi.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "bearjadahke", "laavadahke" ], + "ERANAMES": [ + "ovdal Kristtusa", + "ma\u014b\u014bel Kristtusa" + ], + "ERAS": [ + "o.Kr.", + "m.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "o\u0111\u0111ajagem\u00e1nnu", diff --git a/src/ngLocale/angular-locale_se-no.js b/src/ngLocale/angular-locale_se-no.js index 5aca4e30b42f..b2e24ae6afbb 100644 --- a/src/ngLocale/angular-locale_se-no.js +++ b/src/ngLocale/angular-locale_se-no.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "bearjadat", "l\u00e1vvardat" ], + "ERANAMES": [ + "ovdal Kristtusa", + "ma\u014b\u014bel Kristtusa" + ], + "ERAS": [ + "o.Kr.", + "m.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "o\u0111\u0111ajagem\u00e1nnu", diff --git a/src/ngLocale/angular-locale_se-se.js b/src/ngLocale/angular-locale_se-se.js index 26b1aecd1f6a..7915d431c94a 100644 --- a/src/ngLocale/angular-locale_se-se.js +++ b/src/ngLocale/angular-locale_se-se.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "bearjadat", "l\u00e1vvardat" ], + "ERANAMES": [ + "ovdal Kristtusa", + "ma\u014b\u014bel Kristtusa" + ], + "ERAS": [ + "o.Kr.", + "m.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "o\u0111\u0111ajagem\u00e1nnu", diff --git a/src/ngLocale/angular-locale_se.js b/src/ngLocale/angular-locale_se.js index bc6819d8c86e..0a6d7d665482 100644 --- a/src/ngLocale/angular-locale_se.js +++ b/src/ngLocale/angular-locale_se.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "bearjadat", "l\u00e1vvardat" ], + "ERANAMES": [ + "ovdal Kristtusa", + "ma\u014b\u014bel Kristtusa" + ], + "ERAS": [ + "o.Kr.", + "m.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "o\u0111\u0111ajagem\u00e1nnu", diff --git a/src/ngLocale/angular-locale_seh-mz.js b/src/ngLocale/angular-locale_seh-mz.js index 4e3e2faa92b1..f723c867881d 100644 --- a/src/ngLocale/angular-locale_seh-mz.js +++ b/src/ngLocale/angular-locale_seh-mz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Chishanu", "Sabudu" ], + "ERANAMES": [ + "Antes de Cristo", + "Anno Domini" + ], + "ERAS": [ + "AC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Janeiro", diff --git a/src/ngLocale/angular-locale_seh.js b/src/ngLocale/angular-locale_seh.js index 657b0de14fee..d9c55eecfdd9 100644 --- a/src/ngLocale/angular-locale_seh.js +++ b/src/ngLocale/angular-locale_seh.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Chishanu", "Sabudu" ], + "ERANAMES": [ + "Antes de Cristo", + "Anno Domini" + ], + "ERAS": [ + "AC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Janeiro", diff --git a/src/ngLocale/angular-locale_ses-ml.js b/src/ngLocale/angular-locale_ses-ml.js index 2662cb170e62..596dfe43b05e 100644 --- a/src/ngLocale/angular-locale_ses-ml.js +++ b/src/ngLocale/angular-locale_ses-ml.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Alzuma", "Asibti" ], + "ERANAMES": [ + "Isaa jine", + "Isaa zamanoo" + ], + "ERAS": [ + "IJ", + "IZ" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u017danwiye", diff --git a/src/ngLocale/angular-locale_ses.js b/src/ngLocale/angular-locale_ses.js index 5172997d17e5..e150d779fe21 100644 --- a/src/ngLocale/angular-locale_ses.js +++ b/src/ngLocale/angular-locale_ses.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Alzuma", "Asibti" ], + "ERANAMES": [ + "Isaa jine", + "Isaa zamanoo" + ], + "ERAS": [ + "IJ", + "IZ" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u017danwiye", diff --git a/src/ngLocale/angular-locale_sg-cf.js b/src/ngLocale/angular-locale_sg-cf.js index ecb1b488a0a9..fb6d2f76c8cf 100644 --- a/src/ngLocale/angular-locale_sg-cf.js +++ b/src/ngLocale/angular-locale_sg-cf.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "L\u00e2p\u00f4s\u00f6", "L\u00e2yenga" ], + "ERANAMES": [ + "K\u00f4zo na Kr\u00eestu", + "Na pek\u00f4 t\u00ee Kr\u00eestu" + ], + "ERAS": [ + "KnK", + "NpK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Nyenye", diff --git a/src/ngLocale/angular-locale_sg.js b/src/ngLocale/angular-locale_sg.js index ebf12a9a4425..3b671dae11ef 100644 --- a/src/ngLocale/angular-locale_sg.js +++ b/src/ngLocale/angular-locale_sg.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "L\u00e2p\u00f4s\u00f6", "L\u00e2yenga" ], + "ERANAMES": [ + "K\u00f4zo na Kr\u00eestu", + "Na pek\u00f4 t\u00ee Kr\u00eestu" + ], + "ERAS": [ + "KnK", + "NpK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Nyenye", diff --git a/src/ngLocale/angular-locale_shi-latn-ma.js b/src/ngLocale/angular-locale_shi-latn-ma.js index 5becc56a9817..02156c6921b6 100644 --- a/src/ngLocale/angular-locale_shi-latn-ma.js +++ b/src/ngLocale/angular-locale_shi-latn-ma.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "asimwas", "asi\u1e0dyas" ], + "ERANAMES": [ + "dat n \u025bisa", + "dffir n \u025bisa" + ], + "ERAS": [ + "da\u025b", + "df\u025b" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "innayr", diff --git a/src/ngLocale/angular-locale_shi-latn.js b/src/ngLocale/angular-locale_shi-latn.js index 1108ef3de2bf..7c77378427bb 100644 --- a/src/ngLocale/angular-locale_shi-latn.js +++ b/src/ngLocale/angular-locale_shi-latn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "asimwas", "asi\u1e0dyas" ], + "ERANAMES": [ + "dat n \u025bisa", + "dffir n \u025bisa" + ], + "ERAS": [ + "da\u025b", + "df\u025b" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "innayr", diff --git a/src/ngLocale/angular-locale_shi-tfng-ma.js b/src/ngLocale/angular-locale_shi-tfng-ma.js index 1bbf2519958d..998d17a2f315 100644 --- a/src/ngLocale/angular-locale_shi-tfng-ma.js +++ b/src/ngLocale/angular-locale_shi-tfng-ma.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59", "\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59" ], + "ERANAMES": [ + "\u2d37\u2d30\u2d5c \u2d4f \u2d44\u2d49\u2d59\u2d30", + "\u2d37\u2d3c\u2d3c\u2d49\u2d54 \u2d4f \u2d44\u2d49\u2d59\u2d30" + ], + "ERAS": [ + "\u2d37\u2d30\u2d44", + "\u2d37\u2d3c\u2d44" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54", diff --git a/src/ngLocale/angular-locale_shi-tfng.js b/src/ngLocale/angular-locale_shi-tfng.js index f620789329ce..8f1280d1b72e 100644 --- a/src/ngLocale/angular-locale_shi-tfng.js +++ b/src/ngLocale/angular-locale_shi-tfng.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59", "\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59" ], + "ERANAMES": [ + "\u2d37\u2d30\u2d5c \u2d4f \u2d44\u2d49\u2d59\u2d30", + "\u2d37\u2d3c\u2d3c\u2d49\u2d54 \u2d4f \u2d44\u2d49\u2d59\u2d30" + ], + "ERAS": [ + "\u2d37\u2d30\u2d44", + "\u2d37\u2d3c\u2d44" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54", diff --git a/src/ngLocale/angular-locale_shi.js b/src/ngLocale/angular-locale_shi.js index c2166fc3267f..5f2fe453d200 100644 --- a/src/ngLocale/angular-locale_shi.js +++ b/src/ngLocale/angular-locale_shi.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59", "\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59" ], + "ERANAMES": [ + "\u2d37\u2d30\u2d5c \u2d4f \u2d44\u2d49\u2d59\u2d30", + "\u2d37\u2d3c\u2d3c\u2d49\u2d54 \u2d4f \u2d44\u2d49\u2d59\u2d30" + ], + "ERAS": [ + "\u2d37\u2d30\u2d44", + "\u2d37\u2d3c\u2d44" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54", diff --git a/src/ngLocale/angular-locale_si-lk.js b/src/ngLocale/angular-locale_si-lk.js index 17718227eab4..2989a6411dde 100644 --- a/src/ngLocale/angular-locale_si-lk.js +++ b/src/ngLocale/angular-locale_si-lk.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0dc3\u0dd2\u0d9a\u0dd4\u0dbb\u0dcf\u0daf\u0dcf", "\u0dc3\u0dd9\u0db1\u0dc3\u0dd4\u0dbb\u0dcf\u0daf\u0dcf" ], + "ERANAMES": [ + "\u0d9a\u0dca\u200d\u0dbb\u0dd2\u0dc3\u0dca\u0dad\u0dd4 \u0db4\u0dd6\u0dbb\u0dca\u200d\u0dc0", + "\u0d9a\u0dca\u200d\u0dbb\u0dd2\u0dc3\u0dca\u0dad\u0dd4 \u0dc0\u0dbb\u0dca\u200d\u0dc2" + ], + "ERAS": [ + "\u0d9a\u0dca\u200d\u0dbb\u0dd2.\u0db4\u0dd6.", + "\u0d9a\u0dca\u200d\u0dbb\u0dd2.\u0dc0." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0da2\u0db1\u0dc0\u0dcf\u0dbb\u0dd2", diff --git a/src/ngLocale/angular-locale_si.js b/src/ngLocale/angular-locale_si.js index 27dbaf08d897..96ea0b4cf321 100644 --- a/src/ngLocale/angular-locale_si.js +++ b/src/ngLocale/angular-locale_si.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0dc3\u0dd2\u0d9a\u0dd4\u0dbb\u0dcf\u0daf\u0dcf", "\u0dc3\u0dd9\u0db1\u0dc3\u0dd4\u0dbb\u0dcf\u0daf\u0dcf" ], + "ERANAMES": [ + "\u0d9a\u0dca\u200d\u0dbb\u0dd2\u0dc3\u0dca\u0dad\u0dd4 \u0db4\u0dd6\u0dbb\u0dca\u200d\u0dc0", + "\u0d9a\u0dca\u200d\u0dbb\u0dd2\u0dc3\u0dca\u0dad\u0dd4 \u0dc0\u0dbb\u0dca\u200d\u0dc2" + ], + "ERAS": [ + "\u0d9a\u0dca\u200d\u0dbb\u0dd2.\u0db4\u0dd6.", + "\u0d9a\u0dca\u200d\u0dbb\u0dd2.\u0dc0." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0da2\u0db1\u0dc0\u0dcf\u0dbb\u0dd2", diff --git a/src/ngLocale/angular-locale_sk-sk.js b/src/ngLocale/angular-locale_sk-sk.js index f8e06cd366e3..01f0f0cb42ef 100644 --- a/src/ngLocale/angular-locale_sk-sk.js +++ b/src/ngLocale/angular-locale_sk-sk.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "piatok", "sobota" ], + "ERANAMES": [ + "pred Kristom", + "po Kristovi" + ], + "ERAS": [ + "pred Kr.", + "po Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janu\u00e1ra", diff --git a/src/ngLocale/angular-locale_sk.js b/src/ngLocale/angular-locale_sk.js index fcc1f12e2588..7618fe3835dd 100644 --- a/src/ngLocale/angular-locale_sk.js +++ b/src/ngLocale/angular-locale_sk.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "piatok", "sobota" ], + "ERANAMES": [ + "pred Kristom", + "po Kristovi" + ], + "ERAS": [ + "pred Kr.", + "po Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janu\u00e1ra", diff --git a/src/ngLocale/angular-locale_sl-si.js b/src/ngLocale/angular-locale_sl-si.js index c5a68c1ec403..39502de613ab 100644 --- a/src/ngLocale/angular-locale_sl-si.js +++ b/src/ngLocale/angular-locale_sl-si.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "petek", "sobota" ], + "ERANAMES": [ + "pred na\u0161im \u0161tetjem", + "na\u0161e \u0161tetje" + ], + "ERAS": [ + "pr. n. \u0161t.", + "po Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_sl.js b/src/ngLocale/angular-locale_sl.js index f6dd00e586b9..c3b744aee306 100644 --- a/src/ngLocale/angular-locale_sl.js +++ b/src/ngLocale/angular-locale_sl.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "petek", "sobota" ], + "ERANAMES": [ + "pred na\u0161im \u0161tetjem", + "na\u0161e \u0161tetje" + ], + "ERAS": [ + "pr. n. \u0161t.", + "po Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_smn-fi.js b/src/ngLocale/angular-locale_smn-fi.js index 98e065d85120..67277e453b17 100644 --- a/src/ngLocale/angular-locale_smn-fi.js +++ b/src/ngLocale/angular-locale_smn-fi.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "v\u00e1stuppeeivi", "l\u00e1vurduv" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "M01", diff --git a/src/ngLocale/angular-locale_smn.js b/src/ngLocale/angular-locale_smn.js index 6ad1202fd032..1ca4f965f463 100644 --- a/src/ngLocale/angular-locale_smn.js +++ b/src/ngLocale/angular-locale_smn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "v\u00e1stuppeeivi", "l\u00e1vurduv" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "M01", diff --git a/src/ngLocale/angular-locale_sn-zw.js b/src/ngLocale/angular-locale_sn-zw.js index 8a3f9bac9aa4..9105f7ca6097 100644 --- a/src/ngLocale/angular-locale_sn-zw.js +++ b/src/ngLocale/angular-locale_sn-zw.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Chishanu", "Mugovera" ], + "ERANAMES": [ + "Kristo asati auya", + "Kristo ashaya" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Ndira", diff --git a/src/ngLocale/angular-locale_sn.js b/src/ngLocale/angular-locale_sn.js index 043fa50707b5..9702ee295200 100644 --- a/src/ngLocale/angular-locale_sn.js +++ b/src/ngLocale/angular-locale_sn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Chishanu", "Mugovera" ], + "ERANAMES": [ + "Kristo asati auya", + "Kristo ashaya" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Ndira", diff --git a/src/ngLocale/angular-locale_so-dj.js b/src/ngLocale/angular-locale_so-dj.js index 8cdcfb1feb87..9ce1e30fa89f 100644 --- a/src/ngLocale/angular-locale_so-dj.js +++ b/src/ngLocale/angular-locale_so-dj.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jimco", "Sabti" ], + "ERANAMES": [ + "Ciise ka hor (CS)", + "Ciise ka dib (CS)" + ], + "ERAS": [ + "CK", + "CD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Bisha Koobaad", diff --git a/src/ngLocale/angular-locale_so-et.js b/src/ngLocale/angular-locale_so-et.js index 49fde68cb5ff..d43cbfcdaad1 100644 --- a/src/ngLocale/angular-locale_so-et.js +++ b/src/ngLocale/angular-locale_so-et.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jimco", "Sabti" ], + "ERANAMES": [ + "Ciise ka hor (CS)", + "Ciise ka dib (CS)" + ], + "ERAS": [ + "CK", + "CD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Bisha Koobaad", diff --git a/src/ngLocale/angular-locale_so-ke.js b/src/ngLocale/angular-locale_so-ke.js index e1342bbd759f..8d34e577203c 100644 --- a/src/ngLocale/angular-locale_so-ke.js +++ b/src/ngLocale/angular-locale_so-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jimco", "Sabti" ], + "ERANAMES": [ + "Ciise ka hor (CS)", + "Ciise ka dib (CS)" + ], + "ERAS": [ + "CK", + "CD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Bisha Koobaad", diff --git a/src/ngLocale/angular-locale_so-so.js b/src/ngLocale/angular-locale_so-so.js index 5e3452406127..5ef74834ba62 100644 --- a/src/ngLocale/angular-locale_so-so.js +++ b/src/ngLocale/angular-locale_so-so.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jimco", "Sabti" ], + "ERANAMES": [ + "Ciise ka hor (CS)", + "Ciise ka dib (CS)" + ], + "ERAS": [ + "CK", + "CD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Bisha Koobaad", diff --git a/src/ngLocale/angular-locale_so.js b/src/ngLocale/angular-locale_so.js index 738a9767a745..db85ca0c7815 100644 --- a/src/ngLocale/angular-locale_so.js +++ b/src/ngLocale/angular-locale_so.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jimco", "Sabti" ], + "ERANAMES": [ + "Ciise ka hor (CS)", + "Ciise ka dib (CS)" + ], + "ERAS": [ + "CK", + "CD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Bisha Koobaad", diff --git a/src/ngLocale/angular-locale_sq-al.js b/src/ngLocale/angular-locale_sq-al.js index 2cb020434666..6dac5e79ef1e 100644 --- a/src/ngLocale/angular-locale_sq-al.js +++ b/src/ngLocale/angular-locale_sq-al.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "e premte", "e shtun\u00eb" ], + "ERANAMES": [ + "para er\u00ebs s\u00eb re", + "er\u00ebs s\u00eb re" + ], + "ERAS": [ + "p.e.r.", + "e.r." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janar", diff --git a/src/ngLocale/angular-locale_sq-mk.js b/src/ngLocale/angular-locale_sq-mk.js index 86a006a98a7c..e7f5c31e1bea 100644 --- a/src/ngLocale/angular-locale_sq-mk.js +++ b/src/ngLocale/angular-locale_sq-mk.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "e premte", "e shtun\u00eb" ], + "ERANAMES": [ + "para er\u00ebs s\u00eb re", + "er\u00ebs s\u00eb re" + ], + "ERAS": [ + "p.e.r.", + "e.r." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janar", diff --git a/src/ngLocale/angular-locale_sq-xk.js b/src/ngLocale/angular-locale_sq-xk.js index a4d78d5bd36c..ccdf61f562b6 100644 --- a/src/ngLocale/angular-locale_sq-xk.js +++ b/src/ngLocale/angular-locale_sq-xk.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "e premte", "e shtun\u00eb" ], + "ERANAMES": [ + "para er\u00ebs s\u00eb re", + "er\u00ebs s\u00eb re" + ], + "ERAS": [ + "p.e.r.", + "e.r." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janar", diff --git a/src/ngLocale/angular-locale_sq.js b/src/ngLocale/angular-locale_sq.js index fb7b51758c9e..bc614eedb67f 100644 --- a/src/ngLocale/angular-locale_sq.js +++ b/src/ngLocale/angular-locale_sq.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "e premte", "e shtun\u00eb" ], + "ERANAMES": [ + "para er\u00ebs s\u00eb re", + "er\u00ebs s\u00eb re" + ], + "ERAS": [ + "p.e.r.", + "e.r." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janar", diff --git a/src/ngLocale/angular-locale_sr-cyrl-ba.js b/src/ngLocale/angular-locale_sr-cyrl-ba.js index 9db897d15b6f..3055897b4534 100644 --- a/src/ngLocale/angular-locale_sr-cyrl-ba.js +++ b/src/ngLocale/angular-locale_sr-cyrl-ba.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u0435\u0442\u0430\u043a", "\u0441\u0443\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435", + "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435" + ], + "ERAS": [ + "\u043f. \u043d. \u0435.", + "\u043d. \u0435." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0458\u0430\u043d\u0443\u0430\u0440", diff --git a/src/ngLocale/angular-locale_sr-cyrl-me.js b/src/ngLocale/angular-locale_sr-cyrl-me.js index 02d02f3da01b..3bf9c2cc07b6 100644 --- a/src/ngLocale/angular-locale_sr-cyrl-me.js +++ b/src/ngLocale/angular-locale_sr-cyrl-me.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u0435\u0442\u0430\u043a", "\u0441\u0443\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435", + "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435" + ], + "ERAS": [ + "\u043f. \u043d. \u0435.", + "\u043d. \u0435." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0458\u0430\u043d\u0443\u0430\u0440", diff --git a/src/ngLocale/angular-locale_sr-cyrl-rs.js b/src/ngLocale/angular-locale_sr-cyrl-rs.js index 3a83229090c1..0f883f0bb7c7 100644 --- a/src/ngLocale/angular-locale_sr-cyrl-rs.js +++ b/src/ngLocale/angular-locale_sr-cyrl-rs.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u0435\u0442\u0430\u043a", "\u0441\u0443\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435", + "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435" + ], + "ERAS": [ + "\u043f. \u043d. \u0435.", + "\u043d. \u0435." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0458\u0430\u043d\u0443\u0430\u0440", diff --git a/src/ngLocale/angular-locale_sr-cyrl-xk.js b/src/ngLocale/angular-locale_sr-cyrl-xk.js index 5a3b70b4b31f..cf7c3e2fd49b 100644 --- a/src/ngLocale/angular-locale_sr-cyrl-xk.js +++ b/src/ngLocale/angular-locale_sr-cyrl-xk.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u0435\u0442\u0430\u043a", "\u0441\u0443\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435", + "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435" + ], + "ERAS": [ + "\u043f. \u043d. \u0435.", + "\u043d. \u0435." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0458\u0430\u043d\u0443\u0430\u0440", diff --git a/src/ngLocale/angular-locale_sr-cyrl.js b/src/ngLocale/angular-locale_sr-cyrl.js index b82b91cf9176..325666aed92e 100644 --- a/src/ngLocale/angular-locale_sr-cyrl.js +++ b/src/ngLocale/angular-locale_sr-cyrl.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u0435\u0442\u0430\u043a", "\u0441\u0443\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435", + "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435" + ], + "ERAS": [ + "\u043f. \u043d. \u0435.", + "\u043d. \u0435." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0458\u0430\u043d\u0443\u0430\u0440", diff --git a/src/ngLocale/angular-locale_sr-latn-ba.js b/src/ngLocale/angular-locale_sr-latn-ba.js index da1e8dbae68e..30797d64b2ee 100644 --- a/src/ngLocale/angular-locale_sr-latn-ba.js +++ b/src/ngLocale/angular-locale_sr-latn-ba.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "petak", "subota" ], + "ERANAMES": [ + "Pre nove ere", + "Nove ere" + ], + "ERAS": [ + "p. n. e.", + "n. e." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_sr-latn-me.js b/src/ngLocale/angular-locale_sr-latn-me.js index 7f8e8cece0b0..cc0607a17aef 100644 --- a/src/ngLocale/angular-locale_sr-latn-me.js +++ b/src/ngLocale/angular-locale_sr-latn-me.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "petak", "subota" ], + "ERANAMES": [ + "Pre nove ere", + "Nove ere" + ], + "ERAS": [ + "p. n. e.", + "n. e." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_sr-latn-rs.js b/src/ngLocale/angular-locale_sr-latn-rs.js index 0c88704b27fa..517e8eab6976 100644 --- a/src/ngLocale/angular-locale_sr-latn-rs.js +++ b/src/ngLocale/angular-locale_sr-latn-rs.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "petak", "subota" ], + "ERANAMES": [ + "Pre nove ere", + "Nove ere" + ], + "ERAS": [ + "p. n. e.", + "n. e." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_sr-latn-xk.js b/src/ngLocale/angular-locale_sr-latn-xk.js index 4c071d7b7e2b..1cb50a737a5b 100644 --- a/src/ngLocale/angular-locale_sr-latn-xk.js +++ b/src/ngLocale/angular-locale_sr-latn-xk.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "petak", "subota" ], + "ERANAMES": [ + "Pre nove ere", + "Nove ere" + ], + "ERAS": [ + "p. n. e.", + "n. e." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_sr-latn.js b/src/ngLocale/angular-locale_sr-latn.js index 1239159ac34c..040041da2b3e 100644 --- a/src/ngLocale/angular-locale_sr-latn.js +++ b/src/ngLocale/angular-locale_sr-latn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "petak", "subota" ], + "ERANAMES": [ + "Pre nove ere", + "Nove ere" + ], + "ERAS": [ + "p. n. e.", + "n. e." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januar", diff --git a/src/ngLocale/angular-locale_sr.js b/src/ngLocale/angular-locale_sr.js index 5f85dc128015..15f2f1de24bc 100644 --- a/src/ngLocale/angular-locale_sr.js +++ b/src/ngLocale/angular-locale_sr.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u0435\u0442\u0430\u043a", "\u0441\u0443\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435", + "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435" + ], + "ERAS": [ + "\u043f. \u043d. \u0435.", + "\u043d. \u0435." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0458\u0430\u043d\u0443\u0430\u0440", diff --git a/src/ngLocale/angular-locale_ss-sz.js b/src/ngLocale/angular-locale_ss-sz.js index a58bcf09e240..ae1fdd5f4dea 100644 --- a/src/ngLocale/angular-locale_ss-sz.js +++ b/src/ngLocale/angular-locale_ss-sz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Lesihlanu", "uMgcibelo" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Bhimbidvwane", diff --git a/src/ngLocale/angular-locale_ss-za.js b/src/ngLocale/angular-locale_ss-za.js index 55bcba940ea3..afb5b99b46b6 100644 --- a/src/ngLocale/angular-locale_ss-za.js +++ b/src/ngLocale/angular-locale_ss-za.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Lesihlanu", "uMgcibelo" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Bhimbidvwane", diff --git a/src/ngLocale/angular-locale_ss.js b/src/ngLocale/angular-locale_ss.js index 9d4488d55a77..3ff884606f1d 100644 --- a/src/ngLocale/angular-locale_ss.js +++ b/src/ngLocale/angular-locale_ss.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Lesihlanu", "uMgcibelo" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Bhimbidvwane", diff --git a/src/ngLocale/angular-locale_ssy-er.js b/src/ngLocale/angular-locale_ssy-er.js index 99686db13c13..d4cb8e5dc46e 100644 --- a/src/ngLocale/angular-locale_ssy-er.js +++ b/src/ngLocale/angular-locale_ssy-er.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jumqata", "Qunxa Sambat" ], + "ERANAMES": [ + "Yaasuusuk Duma", + "Yaasuusuk Wadir" + ], + "ERAS": [ + "Yaasuusuk Duma", + "Yaasuusuk Wadir" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Qunxa Garablu", diff --git a/src/ngLocale/angular-locale_ssy.js b/src/ngLocale/angular-locale_ssy.js index a8eaa8462f77..93c0eba09c32 100644 --- a/src/ngLocale/angular-locale_ssy.js +++ b/src/ngLocale/angular-locale_ssy.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Jumqata", "Qunxa Sambat" ], + "ERANAMES": [ + "Yaasuusuk Duma", + "Yaasuusuk Wadir" + ], + "ERAS": [ + "Yaasuusuk Duma", + "Yaasuusuk Wadir" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Qunxa Garablu", diff --git a/src/ngLocale/angular-locale_sv-ax.js b/src/ngLocale/angular-locale_sv-ax.js index 35f4858ecdfe..3c2e1f0d945d 100644 --- a/src/ngLocale/angular-locale_sv-ax.js +++ b/src/ngLocale/angular-locale_sv-ax.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "fredag", "l\u00f6rdag" ], + "ERANAMES": [ + "f\u00f6re Kristus", + "efter Kristus" + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januari", diff --git a/src/ngLocale/angular-locale_sv-fi.js b/src/ngLocale/angular-locale_sv-fi.js index 661fd4a9de17..87ba5ab153b4 100644 --- a/src/ngLocale/angular-locale_sv-fi.js +++ b/src/ngLocale/angular-locale_sv-fi.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "fredag", "l\u00f6rdag" ], + "ERANAMES": [ + "f\u00f6re Kristus", + "efter Kristus" + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januari", diff --git a/src/ngLocale/angular-locale_sv-se.js b/src/ngLocale/angular-locale_sv-se.js index 2c1677657ce9..124285db403c 100644 --- a/src/ngLocale/angular-locale_sv-se.js +++ b/src/ngLocale/angular-locale_sv-se.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "fredag", "l\u00f6rdag" ], + "ERANAMES": [ + "f\u00f6re Kristus", + "efter Kristus" + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januari", diff --git a/src/ngLocale/angular-locale_sv.js b/src/ngLocale/angular-locale_sv.js index 7b5208fc2831..dfd1aa78f503 100644 --- a/src/ngLocale/angular-locale_sv.js +++ b/src/ngLocale/angular-locale_sv.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "fredag", "l\u00f6rdag" ], + "ERANAMES": [ + "f\u00f6re Kristus", + "efter Kristus" + ], + "ERAS": [ + "f.Kr.", + "e.Kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "januari", diff --git a/src/ngLocale/angular-locale_sw-ke.js b/src/ngLocale/angular-locale_sw-ke.js index c136cce1178c..3d89301c2426 100644 --- a/src/ngLocale/angular-locale_sw-ke.js +++ b/src/ngLocale/angular-locale_sw-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Kabla ya Kristo", + "Baada ya Kristo" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_sw-tz.js b/src/ngLocale/angular-locale_sw-tz.js index 5efc51261e83..0f73d503e220 100644 --- a/src/ngLocale/angular-locale_sw-tz.js +++ b/src/ngLocale/angular-locale_sw-tz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Kabla ya Kristo", + "Baada ya Kristo" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_sw-ug.js b/src/ngLocale/angular-locale_sw-ug.js index c96068db7fab..6db525479d8a 100644 --- a/src/ngLocale/angular-locale_sw-ug.js +++ b/src/ngLocale/angular-locale_sw-ug.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Kabla ya Kristo", + "Baada ya Kristo" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_sw.js b/src/ngLocale/angular-locale_sw.js index 2438896e7802..86a7b9086f68 100644 --- a/src/ngLocale/angular-locale_sw.js +++ b/src/ngLocale/angular-locale_sw.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Kabla ya Kristo", + "Baada ya Kristo" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_swc-cd.js b/src/ngLocale/angular-locale_swc-cd.js index 468e55440938..4e51c1565df6 100644 --- a/src/ngLocale/angular-locale_swc-cd.js +++ b/src/ngLocale/angular-locale_swc-cd.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "siku ya tanu", "siku ya sita" ], + "ERANAMES": [ + "mbele ya Yezu Kristo", + "kisha ya Yezu Kristo" + ], + "ERAS": [ + "mbele ya Y", + "kisha ya Y" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "mwezi ya kwanja", diff --git a/src/ngLocale/angular-locale_swc.js b/src/ngLocale/angular-locale_swc.js index c8470b2c74ca..5390f3bfaed3 100644 --- a/src/ngLocale/angular-locale_swc.js +++ b/src/ngLocale/angular-locale_swc.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "siku ya tanu", "siku ya sita" ], + "ERANAMES": [ + "mbele ya Yezu Kristo", + "kisha ya Yezu Kristo" + ], + "ERAS": [ + "mbele ya Y", + "kisha ya Y" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "mwezi ya kwanja", diff --git a/src/ngLocale/angular-locale_ta-in.js b/src/ngLocale/angular-locale_ta-in.js index 0fa6a853c165..bece4fa399d1 100644 --- a/src/ngLocale/angular-locale_ta-in.js +++ b/src/ngLocale/angular-locale_ta-in.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0bb5\u0bc6\u0bb3\u0bcd\u0bb3\u0bbf", "\u0b9a\u0ba9\u0bbf" ], + "ERANAMES": [ + "\u0b95\u0bbf\u0bb1\u0bbf\u0bb8\u0bcd\u0ba4\u0bc1\u0bb5\u0bc1\u0b95\u0bcd\u0b95\u0bc1 \u0bae\u0bc1\u0ba9\u0bcd", + "\u0b85\u0ba9\u0bcb \u0b9f\u0bcb\u0bae\u0bbf\u0ba9\u0bbf" + ], + "ERAS": [ + "\u0b95\u0bbf.\u0bae\u0bc1.", + "\u0b95\u0bbf.\u0baa\u0bbf." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf", diff --git a/src/ngLocale/angular-locale_ta-lk.js b/src/ngLocale/angular-locale_ta-lk.js index ea5d821f8006..8fbd580c169e 100644 --- a/src/ngLocale/angular-locale_ta-lk.js +++ b/src/ngLocale/angular-locale_ta-lk.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0bb5\u0bc6\u0bb3\u0bcd\u0bb3\u0bbf", "\u0b9a\u0ba9\u0bbf" ], + "ERANAMES": [ + "\u0b95\u0bbf\u0bb1\u0bbf\u0bb8\u0bcd\u0ba4\u0bc1\u0bb5\u0bc1\u0b95\u0bcd\u0b95\u0bc1 \u0bae\u0bc1\u0ba9\u0bcd", + "\u0b85\u0ba9\u0bcb \u0b9f\u0bcb\u0bae\u0bbf\u0ba9\u0bbf" + ], + "ERAS": [ + "\u0b95\u0bbf.\u0bae\u0bc1.", + "\u0b95\u0bbf.\u0baa\u0bbf." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf", diff --git a/src/ngLocale/angular-locale_ta-my.js b/src/ngLocale/angular-locale_ta-my.js index 922b327eccbc..952a7b27db18 100644 --- a/src/ngLocale/angular-locale_ta-my.js +++ b/src/ngLocale/angular-locale_ta-my.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0bb5\u0bc6\u0bb3\u0bcd\u0bb3\u0bbf", "\u0b9a\u0ba9\u0bbf" ], + "ERANAMES": [ + "\u0b95\u0bbf\u0bb1\u0bbf\u0bb8\u0bcd\u0ba4\u0bc1\u0bb5\u0bc1\u0b95\u0bcd\u0b95\u0bc1 \u0bae\u0bc1\u0ba9\u0bcd", + "\u0b85\u0ba9\u0bcb \u0b9f\u0bcb\u0bae\u0bbf\u0ba9\u0bbf" + ], + "ERAS": [ + "\u0b95\u0bbf.\u0bae\u0bc1.", + "\u0b95\u0bbf.\u0baa\u0bbf." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf", diff --git a/src/ngLocale/angular-locale_ta-sg.js b/src/ngLocale/angular-locale_ta-sg.js index 0c4512863e5b..27c03f848edb 100644 --- a/src/ngLocale/angular-locale_ta-sg.js +++ b/src/ngLocale/angular-locale_ta-sg.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0bb5\u0bc6\u0bb3\u0bcd\u0bb3\u0bbf", "\u0b9a\u0ba9\u0bbf" ], + "ERANAMES": [ + "\u0b95\u0bbf\u0bb1\u0bbf\u0bb8\u0bcd\u0ba4\u0bc1\u0bb5\u0bc1\u0b95\u0bcd\u0b95\u0bc1 \u0bae\u0bc1\u0ba9\u0bcd", + "\u0b85\u0ba9\u0bcb \u0b9f\u0bcb\u0bae\u0bbf\u0ba9\u0bbf" + ], + "ERAS": [ + "\u0b95\u0bbf.\u0bae\u0bc1.", + "\u0b95\u0bbf.\u0baa\u0bbf." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf", diff --git a/src/ngLocale/angular-locale_ta.js b/src/ngLocale/angular-locale_ta.js index d946a619d9d5..9131d8ecd956 100644 --- a/src/ngLocale/angular-locale_ta.js +++ b/src/ngLocale/angular-locale_ta.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0bb5\u0bc6\u0bb3\u0bcd\u0bb3\u0bbf", "\u0b9a\u0ba9\u0bbf" ], + "ERANAMES": [ + "\u0b95\u0bbf\u0bb1\u0bbf\u0bb8\u0bcd\u0ba4\u0bc1\u0bb5\u0bc1\u0b95\u0bcd\u0b95\u0bc1 \u0bae\u0bc1\u0ba9\u0bcd", + "\u0b85\u0ba9\u0bcb \u0b9f\u0bcb\u0bae\u0bbf\u0ba9\u0bbf" + ], + "ERAS": [ + "\u0b95\u0bbf.\u0bae\u0bc1.", + "\u0b95\u0bbf.\u0baa\u0bbf." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf", diff --git a/src/ngLocale/angular-locale_te-in.js b/src/ngLocale/angular-locale_te-in.js index 851ffa71821b..598f5208abb8 100644 --- a/src/ngLocale/angular-locale_te-in.js +++ b/src/ngLocale/angular-locale_te-in.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0c36\u0c41\u0c15\u0c4d\u0c30\u0c35\u0c3e\u0c30\u0c02", "\u0c36\u0c28\u0c3f\u0c35\u0c3e\u0c30\u0c02" ], + "ERANAMES": [ + "\u0c15\u0c4d\u0c30\u0c40\u0c38\u0c4d\u0c24\u0c41 \u0c2a\u0c42\u0c30\u0c4d\u0c35\u0c02", + "\u0c15\u0c4d\u0c30\u0c40\u0c38\u0c4d\u0c24\u0c41 \u0c36\u0c15\u0c02" + ], + "ERAS": [ + "\u0c15\u0c4d\u0c30\u0c40\u0c2a\u0c42", + "\u0c15\u0c4d\u0c30\u0c40\u0c36" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0c1c\u0c28\u0c35\u0c30\u0c3f", diff --git a/src/ngLocale/angular-locale_te.js b/src/ngLocale/angular-locale_te.js index 9bd89093c5c7..52259d4a74b1 100644 --- a/src/ngLocale/angular-locale_te.js +++ b/src/ngLocale/angular-locale_te.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0c36\u0c41\u0c15\u0c4d\u0c30\u0c35\u0c3e\u0c30\u0c02", "\u0c36\u0c28\u0c3f\u0c35\u0c3e\u0c30\u0c02" ], + "ERANAMES": [ + "\u0c15\u0c4d\u0c30\u0c40\u0c38\u0c4d\u0c24\u0c41 \u0c2a\u0c42\u0c30\u0c4d\u0c35\u0c02", + "\u0c15\u0c4d\u0c30\u0c40\u0c38\u0c4d\u0c24\u0c41 \u0c36\u0c15\u0c02" + ], + "ERAS": [ + "\u0c15\u0c4d\u0c30\u0c40\u0c2a\u0c42", + "\u0c15\u0c4d\u0c30\u0c40\u0c36" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0c1c\u0c28\u0c35\u0c30\u0c3f", diff --git a/src/ngLocale/angular-locale_teo-ke.js b/src/ngLocale/angular-locale_teo-ke.js index e7f7834ee14e..ce19040b4aea 100644 --- a/src/ngLocale/angular-locale_teo-ke.js +++ b/src/ngLocale/angular-locale_teo-ke.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Nakakany", "Nakasabiti" ], + "ERANAMES": [ + "Kabla ya Christo", + "Baada ya Christo" + ], + "ERAS": [ + "KK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Orara", diff --git a/src/ngLocale/angular-locale_teo-ug.js b/src/ngLocale/angular-locale_teo-ug.js index 4a85823a6bab..94961bf3eda5 100644 --- a/src/ngLocale/angular-locale_teo-ug.js +++ b/src/ngLocale/angular-locale_teo-ug.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Nakakany", "Nakasabiti" ], + "ERANAMES": [ + "Kabla ya Christo", + "Baada ya Christo" + ], + "ERAS": [ + "KK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Orara", diff --git a/src/ngLocale/angular-locale_teo.js b/src/ngLocale/angular-locale_teo.js index bd70d49fea6d..ecf2d87e12a0 100644 --- a/src/ngLocale/angular-locale_teo.js +++ b/src/ngLocale/angular-locale_teo.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Nakakany", "Nakasabiti" ], + "ERANAMES": [ + "Kabla ya Christo", + "Baada ya Christo" + ], + "ERAS": [ + "KK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Orara", diff --git a/src/ngLocale/angular-locale_th-th.js b/src/ngLocale/angular-locale_th-th.js index b4a21adae6ad..1e79222152cd 100644 --- a/src/ngLocale/angular-locale_th-th.js +++ b/src/ngLocale/angular-locale_th-th.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0e27\u0e31\u0e19\u0e28\u0e38\u0e01\u0e23\u0e4c", "\u0e27\u0e31\u0e19\u0e40\u0e2a\u0e32\u0e23\u0e4c" ], + "ERANAMES": [ + "\u0e1b\u0e35\u0e01\u0e48\u0e2d\u0e19\u0e04\u0e23\u0e34\u0e2a\u0e15\u0e4c\u0e28\u0e31\u0e01\u0e23\u0e32\u0e0a", + "\u0e04\u0e23\u0e34\u0e2a\u0e15\u0e4c\u0e28\u0e31\u0e01\u0e23\u0e32\u0e0a" + ], + "ERAS": [ + "\u0e1b\u0e35\u0e01\u0e48\u0e2d\u0e19 \u0e04.\u0e28.", + "\u0e04.\u0e28." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21", diff --git a/src/ngLocale/angular-locale_th.js b/src/ngLocale/angular-locale_th.js index cfa46ae870c1..b11acae34faa 100644 --- a/src/ngLocale/angular-locale_th.js +++ b/src/ngLocale/angular-locale_th.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0e27\u0e31\u0e19\u0e28\u0e38\u0e01\u0e23\u0e4c", "\u0e27\u0e31\u0e19\u0e40\u0e2a\u0e32\u0e23\u0e4c" ], + "ERANAMES": [ + "\u0e1b\u0e35\u0e01\u0e48\u0e2d\u0e19\u0e04\u0e23\u0e34\u0e2a\u0e15\u0e4c\u0e28\u0e31\u0e01\u0e23\u0e32\u0e0a", + "\u0e04\u0e23\u0e34\u0e2a\u0e15\u0e4c\u0e28\u0e31\u0e01\u0e23\u0e32\u0e0a" + ], + "ERAS": [ + "\u0e1b\u0e35\u0e01\u0e48\u0e2d\u0e19 \u0e04.\u0e28.", + "\u0e04.\u0e28." + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21", diff --git a/src/ngLocale/angular-locale_ti-er.js b/src/ngLocale/angular-locale_ti-er.js index 40df44696ce4..07de8faf8be7 100644 --- a/src/ngLocale/angular-locale_ti-er.js +++ b/src/ngLocale/angular-locale_ti-er.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u12d3\u122d\u1262", "\u1240\u12f3\u121d" ], + "ERANAMES": [ + "\u12d3/\u12d3", + "\u12d3/\u121d" + ], + "ERAS": [ + "\u12d3/\u12d3", + "\u12d3/\u121d" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u1325\u122a", diff --git a/src/ngLocale/angular-locale_ti-et.js b/src/ngLocale/angular-locale_ti-et.js index 9c909f37f7a3..bb29ded518f0 100644 --- a/src/ngLocale/angular-locale_ti-et.js +++ b/src/ngLocale/angular-locale_ti-et.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u12d3\u122d\u1262", "\u1240\u12f3\u121d" ], + "ERANAMES": [ + "\u12d3/\u12d3", + "\u12d3/\u121d" + ], + "ERAS": [ + "\u12d3/\u12d3", + "\u12d3/\u121d" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u1303\u1295\u12e9\u12c8\u122a", diff --git a/src/ngLocale/angular-locale_ti.js b/src/ngLocale/angular-locale_ti.js index 0d348843ccaa..d4b4271b7de8 100644 --- a/src/ngLocale/angular-locale_ti.js +++ b/src/ngLocale/angular-locale_ti.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u12d3\u122d\u1262", "\u1240\u12f3\u121d" ], + "ERANAMES": [ + "\u12d3/\u12d3", + "\u12d3/\u121d" + ], + "ERAS": [ + "\u12d3/\u12d3", + "\u12d3/\u121d" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u1303\u1295\u12e9\u12c8\u122a", diff --git a/src/ngLocale/angular-locale_tl.js b/src/ngLocale/angular-locale_tl.js index b6794651a361..af11fa387be1 100644 --- a/src/ngLocale/angular-locale_tl.js +++ b/src/ngLocale/angular-locale_tl.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Biyernes", "Sabado" ], + "ERANAMES": [ + "BC", + "AD" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Enero", diff --git a/src/ngLocale/angular-locale_tn-bw.js b/src/ngLocale/angular-locale_tn-bw.js index 944259f43bcc..bc05b8e0a010 100644 --- a/src/ngLocale/angular-locale_tn-bw.js +++ b/src/ngLocale/angular-locale_tn-bw.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Labotlhano", "Matlhatso" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Ferikgong", diff --git a/src/ngLocale/angular-locale_tn-za.js b/src/ngLocale/angular-locale_tn-za.js index fc5acce2b51c..cecb7eeb2631 100644 --- a/src/ngLocale/angular-locale_tn-za.js +++ b/src/ngLocale/angular-locale_tn-za.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Labotlhano", "Matlhatso" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Ferikgong", diff --git a/src/ngLocale/angular-locale_tn.js b/src/ngLocale/angular-locale_tn.js index 8c3b664ab986..f24955606637 100644 --- a/src/ngLocale/angular-locale_tn.js +++ b/src/ngLocale/angular-locale_tn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Labotlhano", "Matlhatso" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Ferikgong", diff --git a/src/ngLocale/angular-locale_to-to.js b/src/ngLocale/angular-locale_to-to.js index 81baf54acda4..9a3985509574 100644 --- a/src/ngLocale/angular-locale_to-to.js +++ b/src/ngLocale/angular-locale_to-to.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Falaite", "Tokonaki" ], + "ERANAMES": [ + "ki mu\u02bba", + "ta\u02bbu \u02bbo S\u012bs\u016b" + ], + "ERAS": [ + "KM", + "TS" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "S\u0101nuali", diff --git a/src/ngLocale/angular-locale_to.js b/src/ngLocale/angular-locale_to.js index 7b9b14435189..d0fd66c9c0fe 100644 --- a/src/ngLocale/angular-locale_to.js +++ b/src/ngLocale/angular-locale_to.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Falaite", "Tokonaki" ], + "ERANAMES": [ + "ki mu\u02bba", + "ta\u02bbu \u02bbo S\u012bs\u016b" + ], + "ERAS": [ + "KM", + "TS" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "S\u0101nuali", diff --git a/src/ngLocale/angular-locale_tr-cy.js b/src/ngLocale/angular-locale_tr-cy.js index 900ae25faa92..ea4847590c90 100644 --- a/src/ngLocale/angular-locale_tr-cy.js +++ b/src/ngLocale/angular-locale_tr-cy.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Cuma", "Cumartesi" ], + "ERANAMES": [ + "Milattan \u00d6nce", + "Milattan Sonra" + ], + "ERAS": [ + "M\u00d6", + "MS" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Ocak", diff --git a/src/ngLocale/angular-locale_tr-tr.js b/src/ngLocale/angular-locale_tr-tr.js index caecd8a674aa..e9575d34e3d5 100644 --- a/src/ngLocale/angular-locale_tr-tr.js +++ b/src/ngLocale/angular-locale_tr-tr.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Cuma", "Cumartesi" ], + "ERANAMES": [ + "Milattan \u00d6nce", + "Milattan Sonra" + ], + "ERAS": [ + "M\u00d6", + "MS" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Ocak", diff --git a/src/ngLocale/angular-locale_tr.js b/src/ngLocale/angular-locale_tr.js index 4452dcc57bbc..e3521251855e 100644 --- a/src/ngLocale/angular-locale_tr.js +++ b/src/ngLocale/angular-locale_tr.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Cuma", "Cumartesi" ], + "ERANAMES": [ + "Milattan \u00d6nce", + "Milattan Sonra" + ], + "ERAS": [ + "M\u00d6", + "MS" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Ocak", diff --git a/src/ngLocale/angular-locale_ts-za.js b/src/ngLocale/angular-locale_ts-za.js index 6bd61413c2bd..077c4a587de7 100644 --- a/src/ngLocale/angular-locale_ts-za.js +++ b/src/ngLocale/angular-locale_ts-za.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ravuntlhanu", "Mugqivela" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Sunguti", diff --git a/src/ngLocale/angular-locale_ts.js b/src/ngLocale/angular-locale_ts.js index 934ac746b567..e5299089e3d8 100644 --- a/src/ngLocale/angular-locale_ts.js +++ b/src/ngLocale/angular-locale_ts.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ravuntlhanu", "Mugqivela" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Sunguti", diff --git a/src/ngLocale/angular-locale_twq-ne.js b/src/ngLocale/angular-locale_twq-ne.js index d2c6e3c7d5e8..6213c47e83e6 100644 --- a/src/ngLocale/angular-locale_twq-ne.js +++ b/src/ngLocale/angular-locale_twq-ne.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Alzuma", "Asibti" ], + "ERANAMES": [ + "Isaa jine", + "Isaa zamanoo" + ], + "ERAS": [ + "IJ", + "IZ" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u017danwiye", diff --git a/src/ngLocale/angular-locale_twq.js b/src/ngLocale/angular-locale_twq.js index b98147f5aab9..b477674ab6d9 100644 --- a/src/ngLocale/angular-locale_twq.js +++ b/src/ngLocale/angular-locale_twq.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Alzuma", "Asibti" ], + "ERANAMES": [ + "Isaa jine", + "Isaa zamanoo" + ], + "ERAS": [ + "IJ", + "IZ" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u017danwiye", diff --git a/src/ngLocale/angular-locale_tzm-latn-ma.js b/src/ngLocale/angular-locale_tzm-latn-ma.js index 716784bc7ffc..bbfe0a7ebe45 100644 --- a/src/ngLocale/angular-locale_tzm-latn-ma.js +++ b/src/ngLocale/angular-locale_tzm-latn-ma.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Asimwas", "Asi\u1e0dyas" ], + "ERANAMES": [ + "Zdat \u0190isa (TA\u0194)", + "\u1e0ceffir \u0190isa (TA\u0194)" + ], + "ERAS": [ + "Z\u0190", + "\u1e0c\u0190" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "Yennayer", diff --git a/src/ngLocale/angular-locale_tzm-latn.js b/src/ngLocale/angular-locale_tzm-latn.js index 4b71c06ed0ce..86c85309e16b 100644 --- a/src/ngLocale/angular-locale_tzm-latn.js +++ b/src/ngLocale/angular-locale_tzm-latn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Asimwas", "Asi\u1e0dyas" ], + "ERANAMES": [ + "Zdat \u0190isa (TA\u0194)", + "\u1e0ceffir \u0190isa (TA\u0194)" + ], + "ERAS": [ + "Z\u0190", + "\u1e0c\u0190" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "Yennayer", diff --git a/src/ngLocale/angular-locale_tzm.js b/src/ngLocale/angular-locale_tzm.js index ac7411587bde..a2f34ff5fa15 100644 --- a/src/ngLocale/angular-locale_tzm.js +++ b/src/ngLocale/angular-locale_tzm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Asimwas", "Asi\u1e0dyas" ], + "ERANAMES": [ + "Zdat \u0190isa (TA\u0194)", + "\u1e0ceffir \u0190isa (TA\u0194)" + ], + "ERAS": [ + "Z\u0190", + "\u1e0c\u0190" + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "Yennayer", diff --git a/src/ngLocale/angular-locale_ug-arab-cn.js b/src/ngLocale/angular-locale_ug-arab-cn.js index 8de3a97cfa6c..4ed96b5bd915 100644 --- a/src/ngLocale/angular-locale_ug-arab-cn.js +++ b/src/ngLocale/angular-locale_ug-arab-cn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u062c\u06c8\u0645\u06d5", "\u0634\u06d5\u0646\u0628\u06d5" ], + "ERANAMES": [ + "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5\u062f\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646", + "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5" + ], + "ERAS": [ + "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5\u062f\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646", + "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u064a\u0627\u0646\u06cb\u0627\u0631", diff --git a/src/ngLocale/angular-locale_ug-arab.js b/src/ngLocale/angular-locale_ug-arab.js index 35aacf02d650..84063d5ba4a2 100644 --- a/src/ngLocale/angular-locale_ug-arab.js +++ b/src/ngLocale/angular-locale_ug-arab.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u062c\u06c8\u0645\u06d5", "\u0634\u06d5\u0646\u0628\u06d5" ], + "ERANAMES": [ + "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5\u062f\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646", + "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5" + ], + "ERAS": [ + "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5\u062f\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646", + "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u064a\u0627\u0646\u06cb\u0627\u0631", diff --git a/src/ngLocale/angular-locale_ug.js b/src/ngLocale/angular-locale_ug.js index 9484d92392b0..9b44379d4e07 100644 --- a/src/ngLocale/angular-locale_ug.js +++ b/src/ngLocale/angular-locale_ug.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u062c\u06c8\u0645\u06d5", "\u0634\u06d5\u0646\u0628\u06d5" ], + "ERANAMES": [ + "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5\u062f\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646", + "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5" + ], + "ERAS": [ + "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5\u062f\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646", + "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u064a\u0627\u0646\u06cb\u0627\u0631", diff --git a/src/ngLocale/angular-locale_uk-ua.js b/src/ngLocale/angular-locale_uk-ua.js index 5015620751d9..1fca063b0443 100644 --- a/src/ngLocale/angular-locale_uk-ua.js +++ b/src/ngLocale/angular-locale_uk-ua.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u02bc\u044f\u0442\u043d\u0438\u0446\u044f", "\u0441\u0443\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u0434\u043e \u043d\u0430\u0448\u043e\u0457 \u0435\u0440\u0438", + "\u043d\u0430\u0448\u043e\u0457 \u0435\u0440\u0438" + ], + "ERAS": [ + "\u0434\u043e \u043d.\u0435.", + "\u043d.\u0435." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0441\u0456\u0447\u043d\u044f", diff --git a/src/ngLocale/angular-locale_uk.js b/src/ngLocale/angular-locale_uk.js index 97cf2f6bfd1f..9519ad862e53 100644 --- a/src/ngLocale/angular-locale_uk.js +++ b/src/ngLocale/angular-locale_uk.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u043f\u02bc\u044f\u0442\u043d\u0438\u0446\u044f", "\u0441\u0443\u0431\u043e\u0442\u0430" ], + "ERANAMES": [ + "\u0434\u043e \u043d\u0430\u0448\u043e\u0457 \u0435\u0440\u0438", + "\u043d\u0430\u0448\u043e\u0457 \u0435\u0440\u0438" + ], + "ERAS": [ + "\u0434\u043e \u043d.\u0435.", + "\u043d.\u0435." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u0441\u0456\u0447\u043d\u044f", diff --git a/src/ngLocale/angular-locale_ur-in.js b/src/ngLocale/angular-locale_ur-in.js index 079c9daa0488..df347ee3efee 100644 --- a/src/ngLocale/angular-locale_ur-in.js +++ b/src/ngLocale/angular-locale_ur-in.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u062c\u0645\u0639\u06c1", "\u06c1\u0641\u062a\u06c1" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0645\u0633\u06cc\u062d", + "\u0639\u06cc\u0633\u0648\u06cc" + ], + "ERAS": [ + "\u0642\u0628\u0644 \u0645\u0633\u06cc\u062d", + "\u0639\u06cc\u0633\u0648\u06cc" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u062c\u0646\u0648\u0631\u06cc", diff --git a/src/ngLocale/angular-locale_ur-pk.js b/src/ngLocale/angular-locale_ur-pk.js index e30fb2a2f8ed..ad80751a9904 100644 --- a/src/ngLocale/angular-locale_ur-pk.js +++ b/src/ngLocale/angular-locale_ur-pk.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u062c\u0645\u0639\u06c1", "\u06c1\u0641\u062a\u06c1" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0645\u0633\u06cc\u062d", + "\u0639\u06cc\u0633\u0648\u06cc \u0633\u0646" + ], + "ERAS": [ + "\u0642 \u0645", + "\u0639\u06cc\u0633\u0648\u06cc \u0633\u0646" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u062c\u0646\u0648\u0631\u06cc", diff --git a/src/ngLocale/angular-locale_ur.js b/src/ngLocale/angular-locale_ur.js index 4c769435dfb6..c2108057ecd0 100644 --- a/src/ngLocale/angular-locale_ur.js +++ b/src/ngLocale/angular-locale_ur.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u062c\u0645\u0639\u06c1", "\u06c1\u0641\u062a\u06c1" ], + "ERANAMES": [ + "\u0642\u0628\u0644 \u0645\u0633\u06cc\u062d", + "\u0639\u06cc\u0633\u0648\u06cc \u0633\u0646" + ], + "ERAS": [ + "\u0642 \u0645", + "\u0639\u06cc\u0633\u0648\u06cc \u0633\u0646" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u062c\u0646\u0648\u0631\u06cc", diff --git a/src/ngLocale/angular-locale_uz-arab-af.js b/src/ngLocale/angular-locale_uz-arab-af.js index 551ae3dd5a8c..118132ae5e8c 100644 --- a/src/ngLocale/angular-locale_uz-arab-af.js +++ b/src/ngLocale/angular-locale_uz-arab-af.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u062c\u0645\u0639\u0647", "\u0634\u0646\u0628\u0647" ], + "ERANAMES": [ + "\u0642.\u0645.", + "\u0645." + ], + "ERAS": [ + "\u0642.\u0645.", + "\u0645." + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u062c\u0646\u0648\u0631\u06cc", diff --git a/src/ngLocale/angular-locale_uz-arab.js b/src/ngLocale/angular-locale_uz-arab.js index 35dd68706481..3f1a20da4fba 100644 --- a/src/ngLocale/angular-locale_uz-arab.js +++ b/src/ngLocale/angular-locale_uz-arab.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u062c\u0645\u0639\u0647", "\u0634\u0646\u0628\u0647" ], + "ERANAMES": [ + "\u0642.\u0645.", + "\u0645." + ], + "ERAS": [ + "\u0642.\u0645.", + "\u0645." + ], "FIRSTDAYOFWEEK": 5, "MONTH": [ "\u062c\u0646\u0648\u0631\u06cc", diff --git a/src/ngLocale/angular-locale_uz-cyrl-uz.js b/src/ngLocale/angular-locale_uz-cyrl-uz.js index ee8854ce40ff..2d1cf486078d 100644 --- a/src/ngLocale/angular-locale_uz-cyrl-uz.js +++ b/src/ngLocale/angular-locale_uz-cyrl-uz.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0436\u0443\u043c\u0430", "\u0448\u0430\u043d\u0431\u0430" ], + "ERANAMES": [ + "\u041c.\u0410.", + "\u042d" + ], + "ERAS": [ + "\u041c.\u0410.", + "\u042d" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u042f\u043d\u0432\u0430\u0440", diff --git a/src/ngLocale/angular-locale_uz-cyrl.js b/src/ngLocale/angular-locale_uz-cyrl.js index 118240e6cf97..ecfb3b808f41 100644 --- a/src/ngLocale/angular-locale_uz-cyrl.js +++ b/src/ngLocale/angular-locale_uz-cyrl.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u0436\u0443\u043c\u0430", "\u0448\u0430\u043d\u0431\u0430" ], + "ERANAMES": [ + "\u041c.\u0410.", + "\u042d" + ], + "ERAS": [ + "\u041c.\u0410.", + "\u042d" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u042f\u043d\u0432\u0430\u0440", diff --git a/src/ngLocale/angular-locale_uz-latn-uz.js b/src/ngLocale/angular-locale_uz-latn-uz.js index 78fd876c0a77..c3a0b24a891d 100644 --- a/src/ngLocale/angular-locale_uz-latn-uz.js +++ b/src/ngLocale/angular-locale_uz-latn-uz.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "juma", "shanba" ], + "ERANAMES": [ + "M.A.", + "E" + ], + "ERAS": [ + "M.A.", + "E" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Yanvar", diff --git a/src/ngLocale/angular-locale_uz-latn.js b/src/ngLocale/angular-locale_uz-latn.js index f9939b0705c8..1684e50debb6 100644 --- a/src/ngLocale/angular-locale_uz-latn.js +++ b/src/ngLocale/angular-locale_uz-latn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "juma", "shanba" ], + "ERANAMES": [ + "M.A.", + "E" + ], + "ERAS": [ + "M.A.", + "E" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Yanvar", diff --git a/src/ngLocale/angular-locale_uz.js b/src/ngLocale/angular-locale_uz.js index 2017b1183e68..3acde23a4904 100644 --- a/src/ngLocale/angular-locale_uz.js +++ b/src/ngLocale/angular-locale_uz.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "juma", "shanba" ], + "ERANAMES": [ + "M.A.", + "E" + ], + "ERAS": [ + "M.A.", + "E" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Yanvar", diff --git a/src/ngLocale/angular-locale_vai-latn-lr.js b/src/ngLocale/angular-locale_vai-latn-lr.js index 2f4dc462ba18..a9681083952b 100644 --- a/src/ngLocale/angular-locale_vai-latn-lr.js +++ b/src/ngLocale/angular-locale_vai-latn-lr.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "aijima", "si\u0253iti" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "luukao kem\u00e3", diff --git a/src/ngLocale/angular-locale_vai-latn.js b/src/ngLocale/angular-locale_vai-latn.js index b0b86cf93900..4eb026b84882 100644 --- a/src/ngLocale/angular-locale_vai-latn.js +++ b/src/ngLocale/angular-locale_vai-latn.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "aijima", "si\u0253iti" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "luukao kem\u00e3", diff --git a/src/ngLocale/angular-locale_vai-vaii-lr.js b/src/ngLocale/angular-locale_vai-vaii-lr.js index 2cd311e48d9b..edae8bae87e7 100644 --- a/src/ngLocale/angular-locale_vai-vaii-lr.js +++ b/src/ngLocale/angular-locale_vai-vaii-lr.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\ua549\ua524\ua540\ua56e", "\ua53b\ua52c\ua533" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\ua5a8\ua56a\ua583 \ua51e\ua56e", diff --git a/src/ngLocale/angular-locale_vai-vaii.js b/src/ngLocale/angular-locale_vai-vaii.js index c409d065c189..659dfc8b7b7a 100644 --- a/src/ngLocale/angular-locale_vai-vaii.js +++ b/src/ngLocale/angular-locale_vai-vaii.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\ua549\ua524\ua540\ua56e", "\ua53b\ua52c\ua533" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\ua5a8\ua56a\ua583 \ua51e\ua56e", diff --git a/src/ngLocale/angular-locale_vai.js b/src/ngLocale/angular-locale_vai.js index 1aaa34d0a54d..56ee9d868d8e 100644 --- a/src/ngLocale/angular-locale_vai.js +++ b/src/ngLocale/angular-locale_vai.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\ua549\ua524\ua540\ua56e", "\ua53b\ua52c\ua533" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\ua5a8\ua56a\ua583 \ua51e\ua56e", diff --git a/src/ngLocale/angular-locale_ve-za.js b/src/ngLocale/angular-locale_ve-za.js index 0939221bd9df..eb526307cbfc 100644 --- a/src/ngLocale/angular-locale_ve-za.js +++ b/src/ngLocale/angular-locale_ve-za.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u1e3cavhu\u1e71anu", "Mugivhela" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Phando", diff --git a/src/ngLocale/angular-locale_ve.js b/src/ngLocale/angular-locale_ve.js index 1f3ba02ae4bb..0acd86f14c26 100644 --- a/src/ngLocale/angular-locale_ve.js +++ b/src/ngLocale/angular-locale_ve.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u1e3cavhu\u1e71anu", "Mugivhela" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Phando", diff --git a/src/ngLocale/angular-locale_vi-vn.js b/src/ngLocale/angular-locale_vi-vn.js index 49092a450388..112e96ae9818 100644 --- a/src/ngLocale/angular-locale_vi-vn.js +++ b/src/ngLocale/angular-locale_vi-vn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Th\u1ee9 S\u00e1u", "Th\u1ee9 B\u1ea3y" ], + "ERANAMES": [ + "tr. CN", + "sau CN" + ], + "ERAS": [ + "tr. CN", + "sau CN" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "th\u00e1ng 1", diff --git a/src/ngLocale/angular-locale_vi.js b/src/ngLocale/angular-locale_vi.js index 42e0443acfbd..be70bd8eb28e 100644 --- a/src/ngLocale/angular-locale_vi.js +++ b/src/ngLocale/angular-locale_vi.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Th\u1ee9 S\u00e1u", "Th\u1ee9 B\u1ea3y" ], + "ERANAMES": [ + "tr. CN", + "sau CN" + ], + "ERAS": [ + "tr. CN", + "sau CN" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "th\u00e1ng 1", diff --git a/src/ngLocale/angular-locale_vo-001.js b/src/ngLocale/angular-locale_vo-001.js index 37718c4b662b..a17a26dac1a6 100644 --- a/src/ngLocale/angular-locale_vo-001.js +++ b/src/ngLocale/angular-locale_vo-001.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "fridel", "z\u00e4del" ], + "ERANAMES": [ + "b. t. kr.", + "p. t. kr." + ], + "ERAS": [ + "b. t. kr.", + "p. t. kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janul", diff --git a/src/ngLocale/angular-locale_vo.js b/src/ngLocale/angular-locale_vo.js index cacc114f332e..f85079931d18 100644 --- a/src/ngLocale/angular-locale_vo.js +++ b/src/ngLocale/angular-locale_vo.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "fridel", "z\u00e4del" ], + "ERANAMES": [ + "b. t. kr.", + "p. t. kr." + ], + "ERAS": [ + "b. t. kr.", + "p. t. kr." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "janul", diff --git a/src/ngLocale/angular-locale_vun-tz.js b/src/ngLocale/angular-locale_vun-tz.js index a3669e854e3a..6324848fc995 100644 --- a/src/ngLocale/angular-locale_vun-tz.js +++ b/src/ngLocale/angular-locale_vun-tz.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Kabla ya Kristu", + "Baada ya Kristu" + ], + "ERAS": [ + "KK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_vun.js b/src/ngLocale/angular-locale_vun.js index b0a248f37065..c21a381de689 100644 --- a/src/ngLocale/angular-locale_vun.js +++ b/src/ngLocale/angular-locale_vun.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Ijumaa", "Jumamosi" ], + "ERANAMES": [ + "Kabla ya Kristu", + "Baada ya Kristu" + ], + "ERAS": [ + "KK", + "BK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Januari", diff --git a/src/ngLocale/angular-locale_wae-ch.js b/src/ngLocale/angular-locale_wae-ch.js index aa8118a28c72..b90664059290 100644 --- a/src/ngLocale/angular-locale_wae-ch.js +++ b/src/ngLocale/angular-locale_wae-ch.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Fritag", "Sam\u0161tag" ], + "ERANAMES": [ + "v. Chr.", + "n. Chr" + ], + "ERAS": [ + "v. Chr.", + "n. Chr" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Jenner", diff --git a/src/ngLocale/angular-locale_wae.js b/src/ngLocale/angular-locale_wae.js index eeb6b1f8dbea..6e51ec8f126d 100644 --- a/src/ngLocale/angular-locale_wae.js +++ b/src/ngLocale/angular-locale_wae.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Fritag", "Sam\u0161tag" ], + "ERANAMES": [ + "v. Chr.", + "n. Chr" + ], + "ERAS": [ + "v. Chr.", + "n. Chr" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Jenner", diff --git a/src/ngLocale/angular-locale_xog-ug.js b/src/ngLocale/angular-locale_xog-ug.js index 9e69ac117f56..0288518ee545 100644 --- a/src/ngLocale/angular-locale_xog-ug.js +++ b/src/ngLocale/angular-locale_xog-ug.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Olokutaanu", "Olomukaaga" ], + "ERANAMES": [ + "Kulisto nga azilawo", + "Kulisto nga affile" + ], + "ERAS": [ + "AZ", + "AF" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Janwaliyo", diff --git a/src/ngLocale/angular-locale_xog.js b/src/ngLocale/angular-locale_xog.js index 823c09ddd221..1a42ccf007c7 100644 --- a/src/ngLocale/angular-locale_xog.js +++ b/src/ngLocale/angular-locale_xog.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "Olokutaanu", "Olomukaaga" ], + "ERANAMES": [ + "Kulisto nga azilawo", + "Kulisto nga affile" + ], + "ERAS": [ + "AZ", + "AF" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Janwaliyo", diff --git a/src/ngLocale/angular-locale_yav-cm.js b/src/ngLocale/angular-locale_yav-cm.js index 1f4edd14c230..142164fcdd2b 100644 --- a/src/ngLocale/angular-locale_yav-cm.js +++ b/src/ngLocale/angular-locale_yav-cm.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "fel\u00e9te", "s\u00e9sel\u00e9" ], + "ERANAMES": [ + "katikup\u00eden Y\u00e9suse", + "\u00e9k\u00e9l\u00e9mk\u00fanup\u00ed\u00e9n n" + ], + "ERAS": [ + "k.Y.", + "+J.C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "pik\u00edt\u00edk\u00edtie, o\u00f3l\u00ed \u00fa kut\u00faan", diff --git a/src/ngLocale/angular-locale_yav.js b/src/ngLocale/angular-locale_yav.js index 2b2cf97c13d9..01781a0d2361 100644 --- a/src/ngLocale/angular-locale_yav.js +++ b/src/ngLocale/angular-locale_yav.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "fel\u00e9te", "s\u00e9sel\u00e9" ], + "ERANAMES": [ + "katikup\u00eden Y\u00e9suse", + "\u00e9k\u00e9l\u00e9mk\u00fanup\u00ed\u00e9n n" + ], + "ERAS": [ + "k.Y.", + "+J.C." + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "pik\u00edt\u00edk\u00edtie, o\u00f3l\u00ed \u00fa kut\u00faan", diff --git a/src/ngLocale/angular-locale_yi-001.js b/src/ngLocale/angular-locale_yi-001.js index 59863ec979eb..18eeb32227a3 100644 --- a/src/ngLocale/angular-locale_yi-001.js +++ b/src/ngLocale/angular-locale_yi-001.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u05e4\u05bf\u05e8\u05f2\u05b7\u05d8\u05d9\u05e7", "\u05e9\u05d1\u05ea" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u05d9\u05d0\u05b7\u05e0\u05d5\u05d0\u05b7\u05e8", diff --git a/src/ngLocale/angular-locale_yi.js b/src/ngLocale/angular-locale_yi.js index 8f28d0361c8e..a7fe164cbfe5 100644 --- a/src/ngLocale/angular-locale_yi.js +++ b/src/ngLocale/angular-locale_yi.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u05e4\u05bf\u05e8\u05f2\u05b7\u05d8\u05d9\u05e7", "\u05e9\u05d1\u05ea" ], + "ERANAMES": [ + "BCE", + "CE" + ], + "ERAS": [ + "BCE", + "CE" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u05d9\u05d0\u05b7\u05e0\u05d5\u05d0\u05b7\u05e8", diff --git a/src/ngLocale/angular-locale_yo-bj.js b/src/ngLocale/angular-locale_yo-bj.js index c333de33e40f..de3dcc5e93e8 100644 --- a/src/ngLocale/angular-locale_yo-bj.js +++ b/src/ngLocale/angular-locale_yo-bj.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u0186j\u0254\u0301 \u0190t\u00ec", "\u0186j\u0254\u0301 \u00c0b\u00e1m\u025b\u0301ta" ], + "ERANAMES": [ + "Saju Kristi", + "Lehin Kristi" + ], + "ERAS": [ + "SK", + "LK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "Osh\u00f9 Sh\u025b\u0301r\u025b\u0301", diff --git a/src/ngLocale/angular-locale_yo-ng.js b/src/ngLocale/angular-locale_yo-ng.js index 1f6284605585..cc8bf1dd04dc 100644 --- a/src/ngLocale/angular-locale_yo-ng.js +++ b/src/ngLocale/angular-locale_yo-ng.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u1eccj\u1ecd\u0301 \u1eb8t\u00ec", "\u1eccj\u1ecd\u0301 \u00c0b\u00e1m\u1eb9\u0301ta" ], + "ERANAMES": [ + "Saju Kristi", + "Lehin Kristi" + ], + "ERAS": [ + "SK", + "LK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "O\u1e63\u00f9 \u1e62\u1eb9\u0301r\u1eb9\u0301", diff --git a/src/ngLocale/angular-locale_yo.js b/src/ngLocale/angular-locale_yo.js index 368c29cd3ad8..3719c3cd176e 100644 --- a/src/ngLocale/angular-locale_yo.js +++ b/src/ngLocale/angular-locale_yo.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u1eccj\u1ecd\u0301 \u1eb8t\u00ec", "\u1eccj\u1ecd\u0301 \u00c0b\u00e1m\u1eb9\u0301ta" ], + "ERANAMES": [ + "Saju Kristi", + "Lehin Kristi" + ], + "ERAS": [ + "SK", + "LK" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "O\u1e63\u00f9 \u1e62\u1eb9\u0301r\u1eb9\u0301", diff --git a/src/ngLocale/angular-locale_zgh-ma.js b/src/ngLocale/angular-locale_zgh-ma.js index 9dea509c5b70..ec0c86b1de2c 100644 --- a/src/ngLocale/angular-locale_zgh-ma.js +++ b/src/ngLocale/angular-locale_zgh-ma.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u2d30\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59", "\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59" ], + "ERANAMES": [ + "\u2d37\u2d30\u2d5c \u2d4f \u2d44\u2d49\u2d59\u2d30", + "\u2d37\u2d3c\u2d3c\u2d49\u2d54 \u2d4f \u2d44\u2d49\u2d59\u2d30" + ], + "ERAS": [ + "\u2d37\u2d30\u2d44", + "\u2d37\u2d3c\u2d44" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54", diff --git a/src/ngLocale/angular-locale_zgh.js b/src/ngLocale/angular-locale_zgh.js index 0956fd4b3e53..c4c7a64e4069 100644 --- a/src/ngLocale/angular-locale_zgh.js +++ b/src/ngLocale/angular-locale_zgh.js @@ -34,6 +34,14 @@ $provide.value("$locale", { "\u2d30\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59", "\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59" ], + "ERANAMES": [ + "\u2d37\u2d30\u2d5c \u2d4f \u2d44\u2d49\u2d59\u2d30", + "\u2d37\u2d3c\u2d3c\u2d49\u2d54 \u2d4f \u2d44\u2d49\u2d59\u2d30" + ], + "ERAS": [ + "\u2d37\u2d30\u2d44", + "\u2d37\u2d3c\u2d44" + ], "FIRSTDAYOFWEEK": 0, "MONTH": [ "\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54", diff --git a/src/ngLocale/angular-locale_zh-cn.js b/src/ngLocale/angular-locale_zh-cn.js index eac0984b5f13..5091db626ee4 100644 --- a/src/ngLocale/angular-locale_zh-cn.js +++ b/src/ngLocale/angular-locale_zh-cn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u661f\u671f\u4e94", "\u661f\u671f\u516d" ], + "ERANAMES": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], + "ERAS": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u4e00\u6708", diff --git a/src/ngLocale/angular-locale_zh-hans-cn.js b/src/ngLocale/angular-locale_zh-hans-cn.js index 4db9dda180d1..1233e35b9ada 100644 --- a/src/ngLocale/angular-locale_zh-hans-cn.js +++ b/src/ngLocale/angular-locale_zh-hans-cn.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u661f\u671f\u4e94", "\u661f\u671f\u516d" ], + "ERANAMES": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], + "ERAS": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u4e00\u6708", diff --git a/src/ngLocale/angular-locale_zh-hans-hk.js b/src/ngLocale/angular-locale_zh-hans-hk.js index 5761cc506ddd..e59cc38a0878 100644 --- a/src/ngLocale/angular-locale_zh-hans-hk.js +++ b/src/ngLocale/angular-locale_zh-hans-hk.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u661f\u671f\u4e94", "\u661f\u671f\u516d" ], + "ERANAMES": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], + "ERAS": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u4e00\u6708", diff --git a/src/ngLocale/angular-locale_zh-hans-mo.js b/src/ngLocale/angular-locale_zh-hans-mo.js index 17111a5ac29e..9921b49e307b 100644 --- a/src/ngLocale/angular-locale_zh-hans-mo.js +++ b/src/ngLocale/angular-locale_zh-hans-mo.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u661f\u671f\u4e94", "\u661f\u671f\u516d" ], + "ERANAMES": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], + "ERAS": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u4e00\u6708", diff --git a/src/ngLocale/angular-locale_zh-hans-sg.js b/src/ngLocale/angular-locale_zh-hans-sg.js index b59501d7366a..425885782dd7 100644 --- a/src/ngLocale/angular-locale_zh-hans-sg.js +++ b/src/ngLocale/angular-locale_zh-hans-sg.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u661f\u671f\u4e94", "\u661f\u671f\u516d" ], + "ERANAMES": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], + "ERAS": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u4e00\u6708", diff --git a/src/ngLocale/angular-locale_zh-hans.js b/src/ngLocale/angular-locale_zh-hans.js index 64bb08c09b8d..8e89da25965c 100644 --- a/src/ngLocale/angular-locale_zh-hans.js +++ b/src/ngLocale/angular-locale_zh-hans.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u661f\u671f\u4e94", "\u661f\u671f\u516d" ], + "ERANAMES": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], + "ERAS": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u4e00\u6708", diff --git a/src/ngLocale/angular-locale_zh-hant-hk.js b/src/ngLocale/angular-locale_zh-hant-hk.js index 5b0b9ccc797b..501220a072fb 100644 --- a/src/ngLocale/angular-locale_zh-hant-hk.js +++ b/src/ngLocale/angular-locale_zh-hant-hk.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u661f\u671f\u4e94", "\u661f\u671f\u516d" ], + "ERANAMES": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "1\u6708", diff --git a/src/ngLocale/angular-locale_zh-hant-mo.js b/src/ngLocale/angular-locale_zh-hant-mo.js index a36930a9aff9..fbc7f1698c57 100644 --- a/src/ngLocale/angular-locale_zh-hant-mo.js +++ b/src/ngLocale/angular-locale_zh-hant-mo.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u661f\u671f\u4e94", "\u661f\u671f\u516d" ], + "ERANAMES": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "1\u6708", diff --git a/src/ngLocale/angular-locale_zh-hant-tw.js b/src/ngLocale/angular-locale_zh-hant-tw.js index dec187c76034..948ec0fc97e2 100644 --- a/src/ngLocale/angular-locale_zh-hant-tw.js +++ b/src/ngLocale/angular-locale_zh-hant-tw.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u661f\u671f\u4e94", "\u661f\u671f\u516d" ], + "ERANAMES": [ + "\u897f\u5143\u524d", + "\u897f\u5143" + ], + "ERAS": [ + "\u897f\u5143\u524d", + "\u897f\u5143" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "1\u6708", diff --git a/src/ngLocale/angular-locale_zh-hant.js b/src/ngLocale/angular-locale_zh-hant.js index a86d36bea850..58d1cded3410 100644 --- a/src/ngLocale/angular-locale_zh-hant.js +++ b/src/ngLocale/angular-locale_zh-hant.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u661f\u671f\u4e94", "\u661f\u671f\u516d" ], + "ERANAMES": [ + "\u897f\u5143\u524d", + "\u897f\u5143" + ], + "ERAS": [ + "\u897f\u5143\u524d", + "\u897f\u5143" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "1\u6708", diff --git a/src/ngLocale/angular-locale_zh-hk.js b/src/ngLocale/angular-locale_zh-hk.js index e9182fa16730..7c602cb0dae9 100644 --- a/src/ngLocale/angular-locale_zh-hk.js +++ b/src/ngLocale/angular-locale_zh-hk.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u661f\u671f\u4e94", "\u661f\u671f\u516d" ], + "ERANAMES": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "1\u6708", diff --git a/src/ngLocale/angular-locale_zh-tw.js b/src/ngLocale/angular-locale_zh-tw.js index 1a6156075cdf..6664f213f9a8 100644 --- a/src/ngLocale/angular-locale_zh-tw.js +++ b/src/ngLocale/angular-locale_zh-tw.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u661f\u671f\u4e94", "\u661f\u671f\u516d" ], + "ERANAMES": [ + "\u897f\u5143\u524d", + "\u897f\u5143" + ], + "ERAS": [ + "\u897f\u5143\u524d", + "\u897f\u5143" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "1\u6708", diff --git a/src/ngLocale/angular-locale_zh.js b/src/ngLocale/angular-locale_zh.js index ecd5f63a74b3..3ce5678fea01 100644 --- a/src/ngLocale/angular-locale_zh.js +++ b/src/ngLocale/angular-locale_zh.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "\u661f\u671f\u4e94", "\u661f\u671f\u516d" ], + "ERANAMES": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], + "ERAS": [ + "\u516c\u5143\u524d", + "\u516c\u5143" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "\u4e00\u6708", diff --git a/src/ngLocale/angular-locale_zu-za.js b/src/ngLocale/angular-locale_zu-za.js index 1eae171e0936..2fa0ba05afed 100644 --- a/src/ngLocale/angular-locale_zu-za.js +++ b/src/ngLocale/angular-locale_zu-za.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Lwesihlanu", "Mgqibelo" ], + "ERANAMES": [ + "BC", + "AD" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Januwari", diff --git a/src/ngLocale/angular-locale_zu.js b/src/ngLocale/angular-locale_zu.js index 4ab4e9fce8fa..359ddc1dee9a 100644 --- a/src/ngLocale/angular-locale_zu.js +++ b/src/ngLocale/angular-locale_zu.js @@ -16,6 +16,14 @@ $provide.value("$locale", { "Lwesihlanu", "Mgqibelo" ], + "ERANAMES": [ + "BC", + "AD" + ], + "ERAS": [ + "BC", + "AD" + ], "FIRSTDAYOFWEEK": 6, "MONTH": [ "Januwari", From 1a37bfd74d66b4a12945cdeae57891c9c3a23895 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 11 Mar 2015 11:58:01 +0000 Subject: [PATCH 106/489] fix(date filter): display localised era for `G` format codes This implementation is limited to displaying only AD (CE) years correctly, since we do not support the `u` style year format that can be used to represent dates before 1 AD. Closes #10503 Closes #11266 --- src/ng/filter/filters.js | 18 ++++++++++++++++-- test/ng/filter/filtersSpec.js | 12 ++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/ng/filter/filters.js b/src/ng/filter/filters.js index 314751cd4a95..77c04bdc58a2 100644 --- a/src/ng/filter/filters.js +++ b/src/ng/filter/filters.js @@ -302,6 +302,14 @@ function ampmGetter(date, formats) { return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1]; } +function eraGetter(date, formats) { + return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1]; +} + +function longEraGetter(date, formats) { + return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1]; +} + var DATE_FORMATS = { yyyy: dateGetter('FullYear', 4), yy: dateGetter('FullYear', 2, 0, true), @@ -328,10 +336,14 @@ var DATE_FORMATS = { a: ampmGetter, Z: timeZoneGetter, ww: weekGetter(2), - w: weekGetter(1) + w: weekGetter(1), + G: eraGetter, + GG: eraGetter, + GGG: eraGetter, + GGGG: longEraGetter }; -var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/, +var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/, NUMBER_STRING = /^\-?\d+$/; /** @@ -368,6 +380,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200) * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year + * * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD') + * * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini') * * `format` string can also be one of the following predefined * {@link guide/i18n localizable formats}: diff --git a/test/ng/filter/filtersSpec.js b/test/ng/filter/filtersSpec.js index 0da8ff0af385..2e7c15a47479 100644 --- a/test/ng/filter/filtersSpec.js +++ b/test/ng/filter/filtersSpec.js @@ -298,6 +298,18 @@ describe('filters', function() { expect(date(earlyDate, "MMMM dd, y")). toEqual('September 03, 1'); + + expect(date(noon, "MMMM dd, y G")). + toEqual('September 03, 2010 AD'); + + expect(date(noon, "MMMM dd, y GG")). + toEqual('September 03, 2010 AD'); + + expect(date(noon, "MMMM dd, y GGG")). + toEqual('September 03, 2010 AD'); + + expect(date(noon, "MMMM dd, y GGGG")). + toEqual('September 03, 2010 Anno Domini'); }); it('should accept negative numbers as strings', function() { From c3f9ae67c19aba0560c28e2a1cc6a4405b9ccd03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rouven=20We=C3=9Fling?= Date: Thu, 5 Mar 2015 01:40:08 +0100 Subject: [PATCH 107/489] test(IE8): remove workarounds for IE8 --- test/ng/compileSpec.js | 20 +++--------- test/ng/directive/inputSpec.js | 50 +++++++++--------------------- test/ng/directive/ngIncludeSpec.js | 6 +--- test/ng/directive/styleSpec.js | 21 +++++-------- 4 files changed, 26 insertions(+), 71 deletions(-) diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index 908739c447a0..d1f97246774c 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -1326,16 +1326,10 @@ describe('$compile', function() { $rootScope.$digest(); - expect(sortedHtml(element)).toBeOneOf( - '
Cau!
', - '
Cau!
' //ie8 - ); + expect(sortedHtml(element)).toBe('
Cau!
'); $httpBackend.flush(); - expect(sortedHtml(element)).toBeOneOf( - '
Hello!Cau!
', - '
Hello!Cau!
' //ie8 - ); + expect(sortedHtml(element)).toBe('
Hello!Cau!
'); } )); @@ -1362,10 +1356,7 @@ describe('$compile', function() { $rootScope.$digest(); - expect(sortedHtml(element)).toBeOneOf( - '
Hello, Elvis!
', - '
Hello, Elvis!
' //ie8 - ); + expect(sortedHtml(element)).toBe('
Hello, Elvis!
'); } )); @@ -1394,10 +1385,7 @@ describe('$compile', function() { element = template($rootScope); $rootScope.$digest(); - expect(sortedHtml(element)).toBeOneOf( - '
Hello, Elvis!
', - '
Hello, Elvis!
' //ie8 - ); + expect(sortedHtml(element)).toBe('
Hello, Elvis!
'); } )); diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index f9640cbf325f..becc6b72aa49 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -551,12 +551,8 @@ describe('input', function() { expect(inputElm.val()).toBe('2013-01'); - try { - //set to text for browsers with datetime-local validation. - inputElm[0].setAttribute('type', 'text'); - } catch (e) { - //for IE8 - } + //set to text for browsers with datetime-local validation. + inputElm[0].setAttribute('type', 'text'); helper.changeInputValueTo('stuff'); expect(inputElm.val()).toBe('stuff'); @@ -776,12 +772,8 @@ describe('input', function() { expect(inputElm.val()).toBe('2013-W02'); - try { - //set to text for browsers with datetime-local validation. - inputElm[0].setAttribute('type', 'text'); - } catch (e) { - //for IE8 - } + //set to text for browsers with datetime-local validation. + inputElm[0].setAttribute('type', 'text'); helper.changeInputValueTo('stuff'); expect(inputElm.val()).toBe('stuff'); @@ -965,12 +957,8 @@ describe('input', function() { expect(inputElm.val()).toBe('2009-01-06T16:25:00.000'); - try { - //set to text for browsers with datetime-local validation. - inputElm[0].setAttribute('type', 'text'); - } catch (e) { - //for IE8 - } + //set to text for browsers with datetime-local validation. + inputElm[0].setAttribute('type', 'text'); helper.changeInputValueTo('stuff'); expect(inputElm.val()).toBe('stuff'); @@ -1277,12 +1265,8 @@ describe('input', function() { expect(inputElm.val()).toBe('16:25:00.000'); - try { - //set to text for browsers with time validation. - inputElm[0].setAttribute('type', 'text'); - } catch (e) { - //for IE8 - } + //set to text for browsers with time validation. + inputElm[0].setAttribute('type', 'text'); helper.changeInputValueTo('stuff'); expect(inputElm.val()).toBe('stuff'); @@ -1571,12 +1555,8 @@ describe('input', function() { expect(inputElm.val()).toBe('2014-09-14'); - try { - //set to text for browsers with date validation. - inputElm[0].setAttribute('type', 'text'); - } catch (e) { - //for IE8 - } + //set to text for browsers with date validation. + inputElm[0].setAttribute('type', 'text'); helper.changeInputValueTo('1-2-3'); expect(inputElm.val()).toBe('1-2-3'); @@ -1843,12 +1823,10 @@ describe('input', function() { $rootScope.$apply('age = 123'); expect(inputElm.val()).toBe('123'); - try { - // to allow non-number values, we have to change type so that - // the browser which have number validation will not interfere with - // this test. IE8 won't allow it hence the catch. - inputElm[0].setAttribute('type', 'text'); - } catch (e) {} + // to allow non-number values, we have to change type so that + // the browser which have number validation will not interfere with + // this test. + inputElm[0].setAttribute('type', 'text'); helper.changeInputValueTo('123X'); expect(inputElm.val()).toBe('123X'); diff --git a/test/ng/directive/ngIncludeSpec.js b/test/ng/directive/ngIncludeSpec.js index b1ec3e735e1f..9cecde9825a8 100644 --- a/test/ng/directive/ngIncludeSpec.js +++ b/test/ng/directive/ngIncludeSpec.js @@ -354,11 +354,7 @@ describe('ngInclude', function() { expect(window._ngIncludeCausesScriptToRun).toBe(true); - // IE8 doesn't like deleting properties of window - window._ngIncludeCausesScriptToRun = undefined; - try { - delete window._ngIncludeCausesScriptToRun; - } catch (e) {} + delete window._ngIncludeCausesScriptToRun; })); diff --git a/test/ng/directive/styleSpec.js b/test/ng/directive/styleSpec.js index 36f15cde1ebb..b42844be21c7 100644 --- a/test/ng/directive/styleSpec.js +++ b/test/ng/directive/styleSpec.js @@ -14,8 +14,7 @@ describe('style', function() { $compile(element)($rootScope); $rootScope.$digest(); - // read innerHTML and trim to pass on IE8 - expect(trim(element[0].innerHTML)).toBe('.header{font-size:1.5em; h3{font-size:1.5em}}'); + expect(element[0].innerHTML).toBe('.header{font-size:1.5em; h3{font-size:1.5em}}'); })); @@ -24,15 +23,13 @@ describe('style', function() { $compile(element)($rootScope); $rootScope.$digest(); - // read innerHTML and trim to pass on IE8 - expect(trim(element[0].innerHTML)).toBe('.some-container{ width: px; }'); + expect(element[0].innerHTML).toBe('.some-container{ width: px; }'); $rootScope.$apply(function() { $rootScope.elementWidth = 200; }); - // read innerHTML and trim to pass on IE8 - expect(trim(element[0].innerHTML)).toBe('.some-container{ width: 200px; }'); + expect(element[0].innerHTML).toBe('.some-container{ width: 200px; }'); })); @@ -41,15 +38,13 @@ describe('style', function() { $compile(element)($rootScope); $rootScope.$digest(); - // read innerHTML and trim to pass on IE8 - expect(trim(element[0].innerHTML)).toBe('.header{ h3 { font-size: em }}'); + expect(element[0].innerHTML).toBe('.header{ h3 { font-size: em }}'); $rootScope.$apply(function() { $rootScope.fontSize = 1.5; }); - // read innerHTML and trim to pass on IE8 - expect(trim(element[0].innerHTML)).toBe('.header{ h3 { font-size: 1.5em }}'); + expect(element[0].innerHTML).toBe('.header{ h3 { font-size: 1.5em }}'); })); @@ -58,16 +53,14 @@ describe('style', function() { $compile(element)($rootScope); $rootScope.$digest(); - // read innerHTML and trim to pass on IE8 - expect(trim(element[0].innerHTML)).toBe('.header{ h3 { font-size: }}'); + expect(element[0].innerHTML).toBe('.header{ h3 { font-size: }}'); $rootScope.$apply(function() { $rootScope.fontSize = 1.5; $rootScope.unit = 'em'; }); - // read innerHTML and trim to pass on IE8 - expect(trim(element[0].innerHTML)).toBe('.header{ h3 { font-size: 1.5em }}'); + expect(element[0].innerHTML).toBe('.header{ h3 { font-size: 1.5em }}'); })); From 70fae4c75ba0a1994fb1a6aa1dc509a0925e5a1e Mon Sep 17 00:00:00 2001 From: Julie Ralph Date: Wed, 11 Mar 2015 10:53:45 -0700 Subject: [PATCH 108/489] chore(ci): turn off verbose logging for sauce connect We have not used the verbose data from these logs for months, and it makes the Travis UI very slow. --- lib/saucelabs/start_tunnel.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/saucelabs/start_tunnel.sh b/lib/saucelabs/start_tunnel.sh index b79b22bc5126..f4431240e012 100755 --- a/lib/saucelabs/start_tunnel.sh +++ b/lib/saucelabs/start_tunnel.sh @@ -46,5 +46,5 @@ echo "Starting Sauce Connect in the background, logging into:" echo " $CONNECT_LOG" echo " $CONNECT_STDOUT" echo " $CONNECT_STDERR" -sauce-connect/bin/sc -u $SAUCE_USERNAME -k $SAUCE_ACCESS_KEY $ARGS -v \ +sauce-connect/bin/sc -u $SAUCE_USERNAME -k $SAUCE_ACCESS_KEY $ARGS \ --logfile $CONNECT_LOG 2> $CONNECT_STDERR 1> $CONNECT_STDOUT & From 3e985442123f358f3c460355bf5e3fc905403997 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Thu, 12 Mar 2015 19:58:38 +0000 Subject: [PATCH 109/489] test(ngMock): test shallow copy of mock controller bindings See #11239 --- test/ngMock/angular-mocksSpec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ngMock/angular-mocksSpec.js b/test/ngMock/angular-mocksSpec.js index 7472dda3345f..f9c7587e86cc 100644 --- a/test/ngMock/angular-mocksSpec.js +++ b/test/ngMock/angular-mocksSpec.js @@ -1764,7 +1764,7 @@ describe('ngMock', function() { module(function($controllerProvider) { $controllerProvider.register('testCtrl', function() { called = true; - expect(this.data).toEqual(data); + expect(this.data).toBe(data); }); }); inject(function($controller, $rootScope) { From 1b37da37e3bad903af8c26d1de29c7f165c3bc03 Mon Sep 17 00:00:00 2001 From: Amy Date: Thu, 12 Mar 2015 08:32:00 -0700 Subject: [PATCH 110/489] docs(guide/Conceptual Overview): add a hyphen for clarity Minor change, but the heading for "View independent business logic..." would be more clear if it had a hyphen, "View-independent". Perhaps it's because I'm new to javascript and its terminology, but I read "View" as a verb rather than a noun on the first pass and had to read on a bit to understand that it was, instead, referring to The View. If you go just by grammar rules, making "view independent" into the compound adjective, "view-independent", makes it clear that it is modifying "business logic". (http://www.grammarbook.com/punctuation/hyphens.asp - see Rule 1). --- docs/content/guide/concepts.ngdoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/guide/concepts.ngdoc b/docs/content/guide/concepts.ngdoc index 08231d810101..de462867a953 100644 --- a/docs/content/guide/concepts.ngdoc +++ b/docs/content/guide/concepts.ngdoc @@ -179,10 +179,10 @@ The following graphic shows how everything works together after we introduced th -## View independent business logic: Services +## View-independent business logic: Services Right now, the `InvoiceController` contains all logic of our example. When the application grows it -is a good practice to move view independent logic from the controller into a +is a good practice to move view-independent logic from the controller into a {@link services service}, so it can be reused by other parts of the application as well. Later on, we could also change that service to load the exchange rates from the web, e.g. by calling the Yahoo Finance API, without changing the controller. From 3ff19669f447f0febbec0fb3a3a1385b045bd641 Mon Sep 17 00:00:00 2001 From: Marcin Wosinek Date: Thu, 12 Mar 2015 14:13:19 +0000 Subject: [PATCH 111/489] docs(ngMessage): move up ngMessages link --- src/ngMessages/messages.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ngMessages/messages.js b/src/ngMessages/messages.js index 26fe64e374f0..5f62858640cb 100644 --- a/src/ngMessages/messages.js +++ b/src/ngMessages/messages.js @@ -531,6 +531,9 @@ angular.module('ngMessages', []) * must be situated since it determines which messages are visible based on the state * of the provided key/value map that `ngMessages` listens on. * + * More information about using `ngMessage` can be found in the + * {@link module:ngMessages `ngMessages` module documentation}. + * * @usage * ```html * @@ -546,8 +549,6 @@ angular.module('ngMessages', []) * * ``` * - * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`. - * * @param {expression} ngMessage|when a string value corresponding to the message key. */ .directive('ngMessage', ngMessageDirectiveFactory('AE')) From 9a492b01672b4f350690ccacee5f87fc3105718f Mon Sep 17 00:00:00 2001 From: Devyn Stott Date: Wed, 11 Mar 2015 13:03:29 -0700 Subject: [PATCH 112/489] docs($log): Add debug button to example Add debug button to example. It was in teh docs but not the example. No breaking changes. --- src/ng/log.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ng/log.js b/src/ng/log.js index 546056bd17a7..29dea20802e4 100644 --- a/src/ng/log.js +++ b/src/ng/log.js @@ -32,6 +32,7 @@ +
From cb7c8de92a912c6ef5aa2f6e78ea8e2a50dfcca2 Mon Sep 17 00:00:00 2001 From: Ciro Nunes Date: Wed, 11 Mar 2015 09:02:46 -0300 Subject: [PATCH 113/489] docs($templateCache): highlight the $templateCache service Closes #11294 --- src/ng/cacheFactory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ng/cacheFactory.js b/src/ng/cacheFactory.js index 41488d45af72..377c0c820d54 100644 --- a/src/ng/cacheFactory.js +++ b/src/ng/cacheFactory.js @@ -372,7 +372,7 @@ function $CacheFactoryProvider() { * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE, * element with ng-app attribute), otherwise the template will be ignored. * - * Adding via the $templateCache service: + * Adding via the `$templateCache` service: * * ```js * var myApp = angular.module('myApp', []); From a4855423f722f981085a75c6582795a42e6d20c8 Mon Sep 17 00:00:00 2001 From: Izhaki Date: Wed, 9 Jul 2014 11:12:32 +0100 Subject: [PATCH 114/489] Added some extra sub-headings for clarity Added `Normalization` and `Directive types`` subheadings to the `Matching directive` heading --- docs/content/guide/directive.ngdoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/content/guide/directive.ngdoc b/docs/content/guide/directive.ngdoc index 77c558aaca9e..13b4c5c0ecec 100644 --- a/docs/content/guide/directive.ngdoc +++ b/docs/content/guide/directive.ngdoc @@ -54,6 +54,8 @@ The following also **matches** `ngModel`: ``` +### Normalization + Angular **normalizes** an element's tag and attribute name to determine which elements match which directives. We typically refer to directives by their case-sensitive [camelCase](http://en.wikipedia.org/wiki/CamelCase) **normalized** name (e.g. `ngModel`). @@ -100,6 +102,8 @@ If you want to use an HTML validating tool, you can instead use the `data`-prefi The other forms shown above are accepted for legacy reasons but we advise you to avoid them.
+### Directive types + `$compile` can match directives based on element names, attributes, class names, as well as comments. All of the Angular-provided directives match attribute name, tag name, comments, or class name. From 2c62e74ea7f12bd0001b7b17c8971bd45df65fde Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 28 Jan 2015 13:36:20 +0000 Subject: [PATCH 115/489] style(ngOptionsSpec): ensure two newlines between specs --- test/ng/directive/ngOptionsSpec.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/ng/directive/ngOptionsSpec.js b/test/ng/directive/ngOptionsSpec.js index 62b3be328734..02eb975edddb 100644 --- a/test/ng/directive/ngOptionsSpec.js +++ b/test/ng/directive/ngOptionsSpec.js @@ -362,6 +362,7 @@ describe('ngOptions', function() { expect(options.eq(2)).toEqualOption(scope.values[2], 'D'); }); + it('should preserve pre-existing empty option', function() { createSingleSelect(true); @@ -855,6 +856,7 @@ describe('ngOptions', function() { expect(options.eq(2)).toEqualTrackedOption(20, 'twenty'); }); + it('should preserve value even when reference has changed (single&array)', function() { createSelect({ 'ng-model': 'selected', From cee6014218742e42d9d58917207626cab0fa025c Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 28 Jan 2015 22:01:52 +0000 Subject: [PATCH 116/489] fix(ngOptions): fix model<->option interaction when using track by This problem is beset by the problem of `ngModel` expecting models to be atomic things (primitives/objects). > When it was first invented it was expected that ngModel would only be a primitive, e.g. a string or a number. Later when things like ngList and ngOptions were added or became more complex then various hacks were put in place to make it look like it worked well with those but it doesn't. ------------- Just to be clear what is happening, lets name the objects: ```js var option1 = { uid: 1, name: 'someName1' }; var option2 = { uid: 2, name: 'someName2' }; var option3 = { uid: 3, name: 'someName3' }; var initialItem = { uid: 1, name: 'someName1' }; model { options: [option1, option2, option3], selected: initialItem }; ``` Now when we begin we have: ```js expect(model.selected).toBe(initialItem); expect(model.selected.uid).toEqual(option1.uid); expect(model.selected).not.toBe(option1); ``` So although `ngOptions` has found a match between an option and the modelValue, these are not the same object. Now if we change the properties of the `model.selected` object, we are effectively changing the `initialItem` object. ```js model.selected.uid = 3; model.selected.name = 'someName3'; expect(model.selected).toBe(initialItem); expect(model.selected.uid).toEqual(option3.uid); expect(model.selected).not.toBe(option3); ``` At the moment `ngModel` only watches for changes to the object identity and so it doesn't trigger an update to the `ngOptions` directive. This commit fixes this in `ngOptions` by adding a **deep** watch on the `attr.ngModel` expression... ```js scope.$watch(attr.ngModel, updateOptions, true); ``` You can see that in this Plunker: http://plnkr.co/edit/0PE7qN5FXIA23y4RwyN0?p=preview ------- But this isn't the end of the story. Since `ngModel` and `ngOptions` did not make copies between the model and the view, we can't go around just changing the properties of the `model.selected` object. This is particularly important in the situation where the user has actually chosen an option, since the `model.selected` points directly to one of the option objects: ```js // User selects "someName2" option expect(model.selected).toBe(option2); expect(model.selected.uid).toEqual(option2.uid); expect(model.selected).not.toBe(initialOption); ``` If we now change the `model.selected` object's properties we are actually changing the `option2` object: ```js expect(model.selected).toBe(option2); model.selected.uid = 3; model.selected.name = 'someName3'; expect(model.selected).toBe(option2); expect(model.selected).not.toBe(option3); expect(option2.uid).toEqual(3); expect(option2.name).toEqual('someName3'); ``` which means that the options are now broken: ```js expect(model.options).toEqual([ { uid: 1, name: 'someName1' }, { uid: 3, name: 'someName3' }, { uid: 3, name: 'someName3' } ]); ``` This commit fixes this in `ngOptions` by making copies when reading the value if `track by` is being used. If we are not using `track by` then we really do care about the identity of the object and should not be copying... You can see this in the Plunker here: http://plnkr.co/edit/YEzEf4dxHTnoW5pbeJDp?p=preview Closes #10869 Closes #10893 --- src/ng/directive/ngOptions.js | 13 ++++- test/ng/directive/ngOptionsSpec.js | 88 ++++++++++++++++++++++++++++-- 2 files changed, 95 insertions(+), 6 deletions(-) diff --git a/src/ng/directive/ngOptions.js b/src/ng/directive/ngOptions.js index 85a725069ee0..476da491d755 100644 --- a/src/ng/directive/ngOptions.js +++ b/src/ng/directive/ngOptions.js @@ -335,6 +335,11 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { selectValueMap: selectValueMap, getOptionFromViewValue: function(value) { return selectValueMap[getTrackByValue(value, getLocals(value))]; + }, + getViewValueFromOption: function(option) { + // If the viewValue could be an object that may be mutated by the application, + // we need to make a copy and not return the reference to the value on the option. + return trackBy ? angular.copy(option.viewValue) : option.viewValue; } }; } @@ -428,7 +433,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { if (selectedOption && !selectedOption.disabled) { removeEmptyOption(); removeUnknownOption(); - return selectedOption.viewValue; + return options.getViewValueFromOption(selectedOption); } return null; }; @@ -462,7 +467,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { forEach(selectedValues, function(value) { var option = options.selectValueMap[value]; - if (!option.disabled) selections.push(option.viewValue); + if (!option.disabled) selections.push(options.getViewValueFromOption(option)); }); return selections; @@ -493,6 +498,10 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { // We will re-render the option elements if the option values or labels change scope.$watchCollection(ngOptions.getWatchables, updateOptions); + // We also need to watch to see if the internals of the model changes, since + // ngModel only watches for object identity change + scope.$watch(attr.ngModel, function() { ngModelCtrl.$render(); }, true); + // ------------------------------------------------------------------ // diff --git a/test/ng/directive/ngOptionsSpec.js b/test/ng/directive/ngOptionsSpec.js index 02eb975edddb..ceb3e312f494 100644 --- a/test/ng/directive/ngOptionsSpec.js +++ b/test/ng/directive/ngOptionsSpec.js @@ -857,6 +857,86 @@ describe('ngOptions', function() { }); + it('should update the selected option even if only the tracked property on the selected object changes (single)', function() { + createSelect({ + 'ng-model': 'selected', + 'ng-options': 'item.label for item in arr track by item.id' + }); + + scope.$apply(function() { + scope.selected = {id: 10, label: 'ten'}; + }); + + expect(element.val()).toEqual('10'); + + // Update the properties on the selected object, rather than replacing the whole object + scope.$apply(function() { + scope.selected.id = 20; + scope.selected.label = 'new twenty'; + }); + + // The value of the select should change since the id property changed + expect(element.val()).toEqual('20'); + + // But the label of the selected option does not change + var option = element.find('option').eq(1); + expect(option.prop('selected')).toEqual(true); + expect(option.text()).toEqual('twenty'); // not 'new twenty' + }); + + + it('should update the selected options even if only the tracked properties on the objects in the ' + + 'selected collection change (multi)', function() { + createSelect({ + 'ng-model': 'selected', + 'multiple': true, + 'ng-options': 'item.label for item in arr track by item.id' + }); + + scope.$apply(function() { + scope.selected = [{id: 10, label: 'ten'}]; + }); + + expect(element.val()).toEqual(['10']); + + // Update the properties on the object in the selected array, rather than replacing the whole object + scope.$apply(function() { + scope.selected[0].id = 20; + scope.selected[0].label = 'new twenty'; + }); + + // The value of the select should change since the id property changed + expect(element.val()).toEqual(['20']); + + // But the label of the selected option does not change + var option = element.find('option').eq(1); + expect(option.prop('selected')).toEqual(true); + expect(option.text()).toEqual('twenty'); // not 'new twenty' + }); + + + it('should prevent changes to the selected object from modifying the options objects (single)', function() { + + createSelect({ + 'ng-model': 'selected', + 'ng-options': 'item.label for item in arr track by item.id' + }); + + element.val('10'); + browserTrigger(element, 'change'); + + expect(scope.selected).toEqual(scope.arr[0]); + + scope.$apply(function() { + scope.selected.id = 20; + }); + + expect(scope.selected).not.toEqual(scope.arr[0]); + expect(element.val()).toEqual('20'); + expect(scope.arr).toEqual([{id: 10, label: 'ten'}, {id:20, label: 'twenty'}]); + }); + + it('should preserve value even when reference has changed (single&array)', function() { createSelect({ 'ng-model': 'selected', @@ -919,7 +999,7 @@ describe('ngOptions', function() { expect(element.val()).toBe('10'); setSelectValue(element, 1); - expect(scope.selected).toBe(scope.obj['2']); + expect(scope.selected).toEqual(scope.obj['2']); }); @@ -998,7 +1078,7 @@ describe('ngOptions', function() { element.val('10'); browserTrigger(element, 'change'); - expect(scope.selected).toBe(scope.arr[0].subItem); + expect(scope.selected).toEqual(scope.arr[0].subItem); // Now reload the array scope.$apply(function() { @@ -1577,7 +1657,7 @@ describe('ngOptions', function() { scope.values.pop(); }); - expect(element.val()).toEqualUnknownValue(); + expect(element.val()).toEqual(''); expect(scope.selected).toEqual(null); // Check after model change @@ -1591,7 +1671,7 @@ describe('ngOptions', function() { scope.values.pop(); }); - expect(element.val()).toEqualUnknownValue(); + expect(element.val()).toEqual(''); expect(scope.selected).toEqual(null); }); From 193bc17471d451bc6a6096b23cbb912a206ade4f Mon Sep 17 00:00:00 2001 From: Julie Ralph Date: Wed, 11 Mar 2015 13:33:43 -0700 Subject: [PATCH 117/489] chore(ci): bump sc version to 4.3.7 --- lib/saucelabs/start_tunnel.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/saucelabs/start_tunnel.sh b/lib/saucelabs/start_tunnel.sh index f4431240e012..c3018da8d2aa 100755 --- a/lib/saucelabs/start_tunnel.sh +++ b/lib/saucelabs/start_tunnel.sh @@ -12,9 +12,9 @@ set -e # before_script: # - curl https://gist.github.com/santiycr/5139565/raw/sauce_connect_setup.sh | bash -CONNECT_URL="https://saucelabs.com/downloads/sc-4.3.6-linux.tar.gz" +CONNECT_URL="https://saucelabs.com/downloads/sc-4.3.7-linux.tar.gz" CONNECT_DIR="/tmp/sauce-connect-$RANDOM" -CONNECT_DOWNLOAD="sc-4.3.6-linux.tar.gz" +CONNECT_DOWNLOAD="sc-4.3.7-linux.tar.gz" CONNECT_LOG="$LOGS_DIR/sauce-connect" CONNECT_STDOUT="$LOGS_DIR/sauce-connect.stdout" From bfbe5b817d3cf12222748cc71ca4990dbf1a7293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Tue, 3 Mar 2015 02:14:30 -0500 Subject: [PATCH 118/489] chore(apis): add HashMap to the DI HashMap will be used inside of angular-animate.js to store details of ongoing animations on a per-element basis. Right now HashMap is only available in core, but this patch will make it available to other areas. Closes #11311 --- src/AngularPublic.js | 2 ++ src/apis.js | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/src/AngularPublic.js b/src/AngularPublic.js index 3b7a644c923d..814a12519799 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -65,6 +65,7 @@ $FilterProvider, $InterpolateProvider, $IntervalProvider, + $$HashMapProvider, $HttpProvider, $HttpBackendProvider, $LocationProvider, @@ -241,6 +242,7 @@ function publishExternalAPI(angular) { $$rAF: $$RAFProvider, $$asyncCallback: $$AsyncCallbackProvider, $$jqLite: $$jqLiteProvider, + $$HashMap: $$HashMapProvider, $$cookieReader: $$CookieReaderProvider }); } diff --git a/src/apis.js b/src/apis.js index 36e0a103ff82..0549730be604 100644 --- a/src/apis.js +++ b/src/apis.js @@ -73,3 +73,9 @@ HashMap.prototype = { return value; } }; + +var $$HashMapProvider = [function() { + this.$get = [function() { + return HashMap; + }]; +}]; From 0e956b352cc685b6c1c20ef036a9ebf19897fb07 Mon Sep 17 00:00:00 2001 From: Amy Date: Fri, 13 Mar 2015 08:01:26 -0700 Subject: [PATCH 119/489] docs(guide/Data Binding): add heading to page the other pages have one, this makes them look more unified. --- docs/content/guide/databinding.ngdoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/content/guide/databinding.ngdoc b/docs/content/guide/databinding.ngdoc index cf03f7aac798..f435c1b3cd02 100644 --- a/docs/content/guide/databinding.ngdoc +++ b/docs/content/guide/databinding.ngdoc @@ -3,6 +3,8 @@ @sortOrder 210 @description +# Data Binding + Data-binding in Angular apps is the automatic synchronization of data between the model and view components. The way that Angular implements data-binding lets you treat the model as the single-source-of-truth in your application. The view is a projection of the model at all times. From c6fb9dea644bd082b5ee6ea3b7f9f8f69931b0f8 Mon Sep 17 00:00:00 2001 From: Amy Date: Fri, 13 Mar 2015 08:05:38 -0700 Subject: [PATCH 120/489] docs(guide/Forms): format headers to match other docs Primary header with page title, secondary headers for each description section. --- docs/content/guide/forms.ngdoc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/content/guide/forms.ngdoc b/docs/content/guide/forms.ngdoc index e691872c118e..a84a754a3207 100644 --- a/docs/content/guide/forms.ngdoc +++ b/docs/content/guide/forms.ngdoc @@ -3,6 +3,8 @@ @sortOrder 290 @description +# Forms + Controls (`input`, `select`, `textarea`) are ways for a user to enter data. A Form is a collection of controls for the purpose of grouping related controls together. @@ -14,7 +16,7 @@ be circumvented and thus can not be trusted. Server-side validation is still nec secure application. -# Simple form +## Simple form The key directive in understanding two-way data-binding is {@link ng.directive:ngModel ngModel}. The `ngModel` directive provides the two-way data-binding by synchronizing the model to the view, as well as view to the model. In addition it provides an {@link ngModel.NgModelController API} @@ -62,7 +64,7 @@ For example: inputs of type `email` must have a value in the form of `user@domai -# Using CSS classes +## Using CSS classes To allow styling of form as well as controls, `ngModel` adds these CSS classes: @@ -126,7 +128,7 @@ and failing to satisfy its validity. -# Binding to form and control state +## Binding to form and control state A form is an instance of {@link form.FormController FormController}. The form instance can optionally be published into the scope using the `name` attribute. @@ -208,7 +210,7 @@ didn't interact with a control -# Custom model update triggers +## Custom model update triggers By default, any change to the content will trigger a model update and form validation. You can override this behavior using the {@link ng.directive:ngModelOptions ngModelOptions} directive to @@ -249,7 +251,7 @@ will update the model only when the control loses focus (blur event). -# Non-immediate (debounced) model updates +## Non-immediate (debounced) model updates You can delay the model update/validation by using the `debounce` key with the {@link ng.directive:ngModelOptions ngModelOptions} directive. This delay will also apply to @@ -290,7 +292,7 @@ after last change. -# Custom Validation +## Custom Validation Angular provides basic implementation for most common HTML5 {@link ng.directive:input input} types: ({@link input[text] text}, {@link input[number] number}, {@link input[url] url}, @@ -407,7 +409,7 @@ In the following example we create two directives: -# Modifying built-in validators +## Modifying built-in validators Since Angular itself uses `$validators`, you can easily replace or remove built-in validators, should you find it necessary. The following example shows you how to overwrite the email validator @@ -452,7 +454,7 @@ Note that you can alternatively use `ng-pattern` to further restrict the validat -# Implementing custom form controls (using `ngModel`) +## Implementing custom form controls (using `ngModel`) Angular implements all of the basic HTML form controls ({@link ng.directive:input input}, {@link ng.directive:select select}, {@link ng.directive:textarea textarea}), which should be sufficient for most cases. However, if you need more flexibility, From dfc1ae9c1c79d1c212bc7863af1ced0ee8b8690a Mon Sep 17 00:00:00 2001 From: Amy Date: Fri, 13 Mar 2015 09:00:08 -0700 Subject: [PATCH 121/489] docs(guide/Controllers): grammar and header fixes fixed a comma and made the headers more logical. --- docs/content/guide/controller.ngdoc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/content/guide/controller.ngdoc b/docs/content/guide/controller.ngdoc index 16d070a6d072..2b641d84917a 100644 --- a/docs/content/guide/controller.ngdoc +++ b/docs/content/guide/controller.ngdoc @@ -30,12 +30,12 @@ Do not use controllers to: services} instead. - Manage the life-cycle of other components (for example, to create service instances). -# Setting up the initial state of a `$scope` object +## Setting up the initial state of a `$scope` object Typically, when you create an application you need to set up the initial state for the Angular `$scope`. You set up the initial state of a scope by attaching properties to the `$scope` object. The properties contain the **view model** (the model that will be presented by the view). All the -`$scope` properties will be available to the template at the point in the DOM where the Controller +`$scope` properties will be available to the {@link templates template} at the point in the DOM where the Controller is registered. The following example demonstrates creating a `GreetingController`, which attaches a `greeting` @@ -69,7 +69,7 @@ now be data-bound to the template: ``` -# Adding Behavior to a Scope Object +## Adding Behavior to a Scope Object In order to react to events or execute computation in the view we must provide behavior to the scope. We add behavior to the scope by attaching methods to the `$scope` object. These methods are @@ -99,7 +99,7 @@ objects (or primitives) assigned to the scope become model properties. Any metho the scope are available in the template/view, and can be invoked via angular expressions and `ng` event handler directives (e.g. {@link ng.directive:ngClick ngClick}). -# Using Controllers Correctly +## Using Controllers Correctly In general, a Controller shouldn't try to do too much. It should contain only the business logic needed for a single view. @@ -125,7 +125,7 @@ following components: - A model consisting of a string named `spice` - A Controller with two functions that set the value of `spice` -The message in our template contains a binding to the `spice` model, which by default is set to the +The message in our template contains a binding to the `spice` model which, by default, is set to the string "very". Depending on which button is clicked, the `spice` model is set to `chili` or `jalapeño`, and the message is automatically updated by data-binding. @@ -259,7 +259,7 @@ Inheritance works with methods in the same way as it does with properties. So in examples, all of the properties could be replaced with methods that return string values. -## Testing Controllers +# Testing Controllers Although there are many ways to test a Controller, one of the best conventions, shown below, involves injecting the {@link ng.$rootScope $rootScope} and {@link ng.$controller $controller}: From 23155d8008fd3bdc38af1b8d73b1ef17e2d43ca2 Mon Sep 17 00:00:00 2001 From: eeue56 Date: Wed, 11 Mar 2015 11:48:49 +0000 Subject: [PATCH 122/489] docs(guide/Services): Fix link to module.Factory --- docs/content/guide/services.ngdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/guide/services.ngdoc b/docs/content/guide/services.ngdoc index 9371b78aff12..19ccae7fc3f1 100644 --- a/docs/content/guide/services.ngdoc +++ b/docs/content/guide/services.ngdoc @@ -82,7 +82,7 @@ on the service. ### Registering Services Services are registered to modules via the {@link angular.Module Module API}. -Typically you use the {@link angular.module Module#factory} API to register a service: +Typically you use the {@link angular.Module#factory Module factory} API to register a service: ```js var myModule = angular.module('myModule', []); From 0aabf9ae2ef1de7c5419ae1fe5052e9129605d9b Mon Sep 17 00:00:00 2001 From: Diego Date: Wed, 11 Mar 2015 19:58:26 -0300 Subject: [PATCH 123/489] refactor(ngPluralize):delete default directive restriction delete the directive restriction to avoid code duplication since the default is already applied Closes #11301 --- src/ng/directive/ngPluralize.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ng/directive/ngPluralize.js b/src/ng/directive/ngPluralize.js index 8a1b11a959e3..57e948484c3e 100644 --- a/src/ng/directive/ngPluralize.js +++ b/src/ng/directive/ngPluralize.js @@ -180,7 +180,6 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale, IS_WHEN = /^when(Minus)?(.+)$/; return { - restrict: 'EA', link: function(scope, element, attr) { var numberExp = attr.count, whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs From 0d923e52475cc845661af1851a3bf89dd243b037 Mon Sep 17 00:00:00 2001 From: rodyhaddad Date: Tue, 10 Mar 2015 13:26:27 -0700 Subject: [PATCH 124/489] chore(security): add warning banner to top of security sensitive files --- src/jqLite.js | 11 +++++++++++ src/ng/compile.js | 11 +++++++++++ src/ng/parse.js | 11 +++++++++++ src/ng/sce.js | 11 +++++++++++ src/ngSanitize/sanitize.js | 11 +++++++++++ 5 files changed, 55 insertions(+) diff --git a/src/jqLite.js b/src/jqLite.js index 5f8338e29001..a59b5d992803 100644 --- a/src/jqLite.js +++ b/src/jqLite.js @@ -1,5 +1,16 @@ 'use strict'; +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + /* global JQLitePrototype: true, addEventListenerFn: true, removeEventListenerFn: true, diff --git a/src/ng/compile.js b/src/ng/compile.js index 3de0d53f0388..1afd08606e8b 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -1,5 +1,16 @@ 'use strict'; +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + /* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE! * * DOM-related variables: diff --git a/src/ng/parse.js b/src/ng/parse.js index 54cad090a5b8..f3386c74e80b 100644 --- a/src/ng/parse.js +++ b/src/ng/parse.js @@ -1,5 +1,16 @@ 'use strict'; +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + var $parseMinErr = minErr('$parse'); // Sandboxing Angular Expressions diff --git a/src/ng/sce.js b/src/ng/sce.js index bedb12f7101d..65cdcb4c5138 100644 --- a/src/ng/sce.js +++ b/src/ng/sce.js @@ -1,5 +1,16 @@ 'use strict'; +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + var $sceMinErr = minErr('$sce'); var SCE_CONTEXTS = { diff --git a/src/ngSanitize/sanitize.js b/src/ngSanitize/sanitize.js index 81302e3ffca4..91d3b2f0ecfe 100644 --- a/src/ngSanitize/sanitize.js +++ b/src/ngSanitize/sanitize.js @@ -1,5 +1,16 @@ 'use strict'; +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + var $sanitizeMinErr = angular.$$minErr('$sanitize'); /** From 4ad0606fa4d2fc7669d149dc78be0409644e75bb Mon Sep 17 00:00:00 2001 From: rodyhaddad Date: Tue, 10 Mar 2015 14:27:10 -0700 Subject: [PATCH 125/489] fix($sanitize): disallow unsafe svg animation tags After #11124 got merged, a security vulnerability got introduced. Animation in SVG became tolerated by the sanitizer. Exploit Example: ``` ``` Here we are animating an anchor's href, starting from a value that's a javascript URI, allowing the executing of arbitrary javascript in the process. Preventing only the animation of links is tricky, as SVG is weird and namespaces aren't predictable. We've decided to have the sanitizer filter out svg animation tags instead. Considering the sanitizer is commonly used to sanitize untrusted HTML code, this shouldn't affect many apps in the wild. Also, no release has been with #11124 in it, but not this fix. Closes #11290 --- src/ngSanitize/sanitize.js | 38 ++++++++++++++++----------------- test/ngSanitize/sanitizeSpec.js | 9 ++++++++ 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/ngSanitize/sanitize.js b/src/ngSanitize/sanitize.js index 91d3b2f0ecfe..9240309c5b48 100644 --- a/src/ngSanitize/sanitize.js +++ b/src/ngSanitize/sanitize.js @@ -206,10 +206,11 @@ var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a // SVG Elements // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements -var svgElements = makeMap("animate,animateColor,animateMotion,animateTransform,circle,defs," + - "desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient," + - "line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set," + - "stop,svg,switch,text,title,tspan,use"); +// Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted. +// They can potentially allow for arbitrary javascript to be executed. See #11290 +var svgElements = makeMap("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph," + + "hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline," + + "radialGradient,rect,stop,svg,switch,text,title,tspan,use"); // Special Elements (can contain anything) var specialElements = makeMap("script,style"); @@ -233,21 +234,20 @@ var htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspac // SVG attributes (without "id" and "name" attributes) // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes var svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' + - 'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,' + - 'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,' + - 'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,' + - 'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,' + - 'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,' + - 'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,' + - 'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,' + - 'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,' + - 'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,' + - 'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,' + - 'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,' + - 'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,' + - 'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,' + - 'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,' + - 'zoomAndPan', true); + 'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' + + 'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' + + 'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' + + 'height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,' + + 'marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,' + + 'max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,' + + 'path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,' + + 'requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,' + + 'stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,' + + 'stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,' + + 'stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,' + + 'underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,' + + 'width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,' + + 'xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan', true); var validAttrs = angular.extend({}, uriAttrs, diff --git a/test/ngSanitize/sanitizeSpec.js b/test/ngSanitize/sanitizeSpec.js index 121d3284736f..33d036c97efc 100644 --- a/test/ngSanitize/sanitizeSpec.js +++ b/test/ngSanitize/sanitizeSpec.js @@ -273,6 +273,15 @@ describe('HTML', function() { .toEqual(''); }); + it('should not accept SVG animation tags', function() { + expectHTML('Click me') + .toEqual('Click me'); + + expectHTML('' + + '') + .toEqual(''); + }); + describe('htmlSanitizerWriter', function() { /* global htmlSanitizeWriter: false */ if (angular.isUndefined(window.htmlSanitizeWriter)) return; From f9b624a822123f0aa29feaf31c6908815a5a936c Mon Sep 17 00:00:00 2001 From: svershin Date: Sat, 14 Mar 2015 12:12:23 +0200 Subject: [PATCH 126/489] docs(misc/Downloading): update o latest stable version Updated the CDN link and description to 1.3.14 Closes #11327 --- docs/content/misc/downloading.ngdoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/misc/downloading.ngdoc b/docs/content/misc/downloading.ngdoc index 6737adf64d28..e96b607eaacd 100644 --- a/docs/content/misc/downloading.ngdoc +++ b/docs/content/misc/downloading.ngdoc @@ -15,14 +15,14 @@ development. production. To point your code to an angular script on the Google CDN server, use the following template. This -example points to the minified version 1.3.12: +example points to the minified version 1.3.14: ``` My Angular App - + From 4ab129fdb98b406b0b42747521677223c744d473 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Tue, 17 Mar 2015 12:06:22 +0000 Subject: [PATCH 127/489] docs(CHANGELOG): add changes for 1.4.0-beta.6 and 1.3.15 --- CHANGELOG.md | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8650464d59f3..898ef13e925d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,169 @@ + +# 1.4.0-beta.6 cookie-liberation (2015-03-17) + + +## Bug Fixes + +- **$animate:** call `applyStyles` from options on `leave` + ([4374f892](https://github.com/angular/angular.js/commit/4374f892c6fa4af6ba1f2ed47c5f888fdb5fadc5), + [#10068](https://github.com/angular/angular.js/issues/10068)) +- **$browser:** don't crash if `history.state` access causes error in IE + ([3b8163b7](https://github.com/angular/angular.js/commit/3b8163b7b664f24499e75460ab50c066eaec0f78), + [#10367](https://github.com/angular/angular.js/issues/10367), [#10369](https://github.com/angular/angular.js/issues/10369)) +- **$sanitize:** disallow unsafe svg animation tags + ([67688d5c](https://github.com/angular/angular.js/commit/67688d5ca00f6de4c7fe6084e2fa762a00d25610), + [#11290](https://github.com/angular/angular.js/issues/11290)) +- **Angular:** properly compare RegExp with other objects for equality + ([f22e1fc9](https://github.com/angular/angular.js/commit/f22e1fc9610ae111a3ea8746a3a57169c99ce142), + [#11204](https://github.com/angular/angular.js/issues/11204), [#11205](https://github.com/angular/angular.js/issues/11205)) +- **date filter:** display localised era for `G` format codes + ([2b4dfa9e](https://github.com/angular/angular.js/commit/2b4dfa9e2b63d7ebb78f3b0fd3439d18f932e1cd), + [#10503](https://github.com/angular/angular.js/issues/10503), [#11266](https://github.com/angular/angular.js/issues/11266)) +- **filterFilter:** + - fix filtering using an object expression when the filter value is undefined + ([c62fa6bd](https://github.com/angular/angular.js/commit/c62fa6bd898e1048d4690d41034489dc60ba6ac2), + [#10419](https://github.com/angular/angular.js/issues/10419), [#10424](https://github.com/angular/angular.js/issues/10424)) + - do not throw an error if property is null when comparing objects + ([2c4ffd6a](https://github.com/angular/angular.js/commit/2c4ffd6af4eb012c4054fe7c096267bbc5510af0), + [#10991](https://github.com/angular/angular.js/issues/10991), [#10992](https://github.com/angular/angular.js/issues/10992), [#11116](https://github.com/angular/angular.js/issues/11116)) +- **form:** allow dynamic form names which initially evaluate to blank + ([410f7c68](https://github.com/angular/angular.js/commit/410f7c682633c681be641cd2a321f9e51671d474)) +- **jqLite:** attr should ignore comment, text and attribute nodes + ([bb5bf7f8](https://github.com/angular/angular.js/commit/bb5bf7f8162d11610a53428e630b47030bdc38e5)) +- **ng/$locale:** add ERA info in generic locale + ([4acb0af2](https://github.com/angular/angular.js/commit/4acb0af24c7fb3705a197ca96adc532de4766a7a)) +- **ngJq:** don't rely on existence of jqlite + ([342e5f3c](https://github.com/angular/angular.js/commit/342e5f3ce38d2fd10c5d5a98ca66f864286a7922), + [#11044](https://github.com/angular/angular.js/issues/11044)) +- **ngMessages:** ensure that multi-level transclusion works with `ngMessagesInclude` + ([d7ec5f39](https://github.com/angular/angular.js/commit/d7ec5f392e1550658ddf271a30627b1749eccb69), + [#11196](https://github.com/angular/angular.js/issues/11196)) +- **ngOptions:** fix model<->option interaction when using `track by` + ([6a03ca27](https://github.com/angular/angular.js/commit/6a03ca274314352052c3082163367a146bb11c2d), + [#10869](https://github.com/angular/angular.js/issues/10869), [#10893](https://github.com/angular/angular.js/issues/10893)) +- **rootScope:** prevent memory leak when destroying scopes + ([fb7db4a0](https://github.com/angular/angular.js/commit/fb7db4a07bd1b0b67824d3808fe315419b272689), + [#11173](https://github.com/angular/angular.js/issues/11173), [#11169](https://github.com/angular/angular.js/issues/11169)) + + +## Features + +- **$cookies:** + - allow passing cookie options + ([92c366d2](https://github.com/angular/angular.js/commit/92c366d205da36ec26502aded23db71a6473dad7), + [#8324](https://github.com/angular/angular.js/issues/8324), [#3988](https://github.com/angular/angular.js/issues/3988), [#1786](https://github.com/angular/angular.js/issues/1786), [#950](https://github.com/angular/angular.js/issues/950)) + - move logic into $cookies and deprecate $cookieStore + ([38fbe3ee](https://github.com/angular/angular.js/commit/38fbe3ee8370fc449b82d80df07b5c2ed2cd5fbe), + [#6411](https://github.com/angular/angular.js/issues/6411), [#7631](https://github.com/angular/angular.js/issues/7631)) +- **$cookiesProvider:** provide path, domain, expires and secure options + ([53c66369](https://github.com/angular/angular.js/commit/53c663699126815eabc2a3bc1e3bafc8b3874268)) +- **$interval:** pass additional arguments to the callback + ([4f1f9cfd](https://github.com/angular/angular.js/commit/4f1f9cfdb721cf308ca1162b2227836dc1d28388), + [#10632](https://github.com/angular/angular.js/issues/10632)) +- **$timeout:** pass additional arguments to the callback + ([3a4b6b83](https://github.com/angular/angular.js/commit/3a4b6b83efdb8051e5c4803c0892c19ceb2cba50), + [#10631](https://github.com/angular/angular.js/issues/10631)) +- **angular.merge:** provide an alternative to `angular.extend` that merges 'deeply' + ([c0498d45](https://github.com/angular/angular.js/commit/c0498d45feb913c318224ea70b5adf7112df6bac), + [#10507](https://github.com/angular/angular.js/issues/10507), [#10519](https://github.com/angular/angular.js/issues/10519)) +- **filterFilter:** compare object with custom `toString()` to primitive + ([f8c42161](https://github.com/angular/angular.js/commit/f8c421617096a8d613f4eb6d0f5b098ee149c029), + [#10464](https://github.com/angular/angular.js/issues/10464), [#10548](https://github.com/angular/angular.js/issues/10548)) +- **ngAria:** + - add `button` role to `ngClick` + ([bb365070](https://github.com/angular/angular.js/commit/bb365070a3ed7c2d26056d378ab6a8ef493b23cc), + [#9254](https://github.com/angular/angular.js/issues/9254), [#10318](https://github.com/angular/angular.js/issues/10318)) + - add roles to custom inputs + ([29cdaee2](https://github.com/angular/angular.js/commit/29cdaee2b6e853bc3f8882a00661698d146ecd18), + [#10012](https://github.com/angular/angular.js/issues/10012), [#10318](https://github.com/angular/angular.js/issues/10318)) +- **ngLocale:** Add FIRSTDAYOFWEEK and WEEKENDRANGE from google data + ([3d149c7f](https://github.com/angular/angular.js/commit/3d149c7f20ffabab5a635af9ddcfc7105112ab4a)) +- **ngMock:** + - allow mock $controller service to set up controller bindings + ([d02d0585](https://github.com/angular/angular.js/commit/d02d0585a086ecd2e1de628218b5a6d85c8fc7bd), + [#9425](https://github.com/angular/angular.js/issues/9425), [#11239](https://github.com/angular/angular.js/issues/11239)) + - add `they` helpers for testing multiple specs + ([e650c458](https://github.com/angular/angular.js/commit/e650c45894abe6314a806e6b3e32c908df5c00fd), + [#10864](https://github.com/angular/angular.js/issues/10864)) +- **ngModel:** support conversion to timezone other than UTC + ([0413bee8](https://github.com/angular/angular.js/commit/0413bee8cc563a6555f8d42d5f183f6fbefc7350), + [#11005](https://github.com/angular/angular.js/issues/11005)) + + +## Breaking Changes + +- **$cookies:** due to [38fbe3ee](https://github.com/angular/angular.js/commit/38fbe3ee8370fc449b82d80df07b5c2ed2cd5fbe), + + +`$cookies` no longer exposes properties that represent the current browser cookie +values. Now you must explicitly the methods described above to access the cookie +values. This also means that you can no longer watch the `$cookies` properties for +changes to the browser's cookies. + +This feature is generally only needed if a 3rd party library was programmatically +changing the cookies at runtime. If you rely on this then you must either write code that +can react to the 3rd party library making the changes to cookies or implement your own polling +mechanism. + + + + + +# 1.3.15 locality-filtration (2015-03-17) + +## Bug Fixes + +- **$animate:** call `applyStyles` with options on `leave` + ([ebd84e80](https://github.com/angular/angular.js/commit/ebd84e8008f45ccaa84290f6da8c2a114fcfa8cd), + [#10068](https://github.com/angular/angular.js/issues/10068)) +- **$browser:** don't crash if history.state access causes error in IE + ([92767c09](https://github.com/angular/angular.js/commit/92767c098feaf8c58faf2d67f882305019d8160e), + [#10367](https://github.com/angular/angular.js/issues/10367), [#10369](https://github.com/angular/angular.js/issues/10369)) +- **Angular:** properly compare RegExp with other objects for equality + ([b8e8f9af](https://github.com/angular/angular.js/commit/b8e8f9af78f4ef3e556dd3cef6bfee35ad4cb82a), + [#11204](https://github.com/angular/angular.js/issues/11204), [#11205](https://github.com/angular/angular.js/issues/11205)) +- **date filter:** display localised era for `G` format codes + ([f2683f95](https://github.com/angular/angular.js/commit/f2683f956fcd3216eaa263db20b31e0d46338800), + [#10503](https://github.com/angular/angular.js/issues/10503), [#11266](https://github.com/angular/angular.js/issues/11266)) +- **filterFilter:** + - fix filtering using an object expression when the filter value is `undefined` + ([63b9956f](https://github.com/angular/angular.js/commit/63b9956faf4c3679c88a9401b8ccbb111c0294ee), + [#10419](https://github.com/angular/angular.js/issues/10419), [#10424](https://github.com/angular/angular.js/issues/10424)) + - do not throw an error if property is null when comparing objects + ([01161a0e](https://github.com/angular/angular.js/commit/01161a0e9fb1af93e9f06535aed8392ed7f116a4), + [#10991](https://github.com/angular/angular.js/issues/10991), [#10992](https://github.com/angular/angular.js/issues/10992), [#11116](https://github.com/angular/angular.js/issues/11116)) +- **form:** allow dynamic form names which initially evaluate to blank + ([190ea883](https://github.com/angular/angular.js/commit/190ea883c588d63f8b900a8de1d45c6c9ebb01ec), + [#11096](https://github.com/angular/angular.js/issues/11096)) +- **ng/$locale:** add ERA info in generic locale + ([57842530](https://github.com/angular/angular.js/commit/578425303f2480959da80f31920d08f277d42010)) +- **rootScope:** prevent memory leak when destroying scopes + ([528cf09e](https://github.com/angular/angular.js/commit/528cf09e3f78ad4e3bb6a329ebe315c4f29b4cdb), + [#11173](https://github.com/angular/angular.js/issues/11173), [#11169](https://github.com/angular/angular.js/issues/11169)) +- **templateRequest:** avoid throwing syntax error in Android 2.3 + ([75abbd52](https://github.com/angular/angular.js/commit/75abbd525f07866fdcc6fb311802b8fe700af174), + [#11089](https://github.com/angular/angular.js/issues/11089), [#11051](https://github.com/angular/angular.js/issues/11051), [#11088](https://github.com/angular/angular.js/issues/11088)) + + +## Features + +- **ngAria:** + - add `button` role to `ngClick` + ([b9ad91cf](https://github.com/angular/angular.js/commit/b9ad91cf1e86310a2d2bf13b29fa13a9b835e1ce), + [#9254](https://github.com/angular/angular.js/issues/9254), [#10318](https://github.com/angular/angular.js/issues/10318)) + - add roles to custom inputs + ([21369943](https://github.com/angular/angular.js/commit/21369943fafd577b36827a641b021b1c14cefb57), + [#10012](https://github.com/angular/angular.js/issues/10012), [#10318](https://github.com/angular/angular.js/issues/10318)) +- **ngMock:** + - allow mock $controller service to set up controller bindings + ([b3878a36](https://github.com/angular/angular.js/commit/b3878a36d9f8e56ad7be1eedb9691c9bd12568cb), + [#9425](https://github.com/angular/angular.js/issues/9425), [#11239](https://github.com/angular/angular.js/issues/11239)) + - add `they` helpers for testing multiple specs + ([7288be25](https://github.com/angular/angular.js/commit/7288be25a75d6ca6ac7eca05a7d6b12ccb3a22f8), + [#10864](https://github.com/angular/angular.js/issues/10864)) + + + # 1.4.0-beta.5 karmic-stabilization (2015-02-24) From 3498b2b3352c133fbc9b42b91eb13a2bf9b1aab3 Mon Sep 17 00:00:00 2001 From: James Talmage Date: Fri, 13 Mar 2015 22:20:35 -0400 Subject: [PATCH 128/489] fix($compile): update data() when controller returns custom value When controller functions return an explicit value that value should be what is passed to the linking functions, and to any child/sibling controllers that `require` it. It should also be bound to the data store on the dom element. Closes #11147 Closes #11326 --- src/ng/compile.js | 16 +++--- test/ng/compileSpec.js | 124 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 7 deletions(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index 1afd08606e8b..9301582e904c 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -1978,13 +1978,15 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { for (i in elementControllers) { controller = elementControllers[i]; var controllerResult = controller(); - if (controllerResult !== controller.instance && - controller === controllerForBindings) { - // Remove and re-install bindToController bindings - thisLinkFn.$$destroyBindings(); - thisLinkFn.$$destroyBindings = - initializeDirectiveBindings(scope, attrs, controllerResult, - bindings, scopeDirective); + if (controllerResult !== controller.instance) { + controller.instance = controllerResult; + $element.data('$' + directive.name + 'Controller', controllerResult); + if (controller === controllerForBindings) { + // Remove and re-install bindToController bindings + thisLinkFn.$$destroyBindings(); + thisLinkFn.$$destroyBindings = + initializeDirectiveBindings(scope, attrs, controllerResult, bindings, scopeDirective); + } } } } diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index d1f97246774c..b30ab8631d9a 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -4197,6 +4197,130 @@ describe('$compile', function() { }); + it('should respect explicit return value from controller', function() { + module(function() { + directive('logControllerProp', function(log) { + return { + controller: function($scope) { + this.foo = 'baz'; // value should not be used. + return {foo: 'bar'}; + }, + link: function(scope, element, attrs, controller) { + log(controller.foo); + } + }; + }); + }); + inject(function(log, $compile, $rootScope) { + element = $compile('')($rootScope); + expect(log).toEqual('bar'); + expect(element.data('$logControllerPropController').foo).toEqual('bar'); + }); + }); + + + it('should get explicit return value of required parent controller', function() { + module(function() { + directive('nested', function(log) { + return { + require: '^^?nested', + controller: function() { + return {foo: 'bar'}; + }, + link: function(scope, element, attrs, controller) { + log(!!controller && controller.foo); + } + }; + }); + }); + inject(function(log, $compile, $rootScope) { + element = $compile('
')($rootScope); + + expect(log).toEqual('bar; false'); + }); + }); + + + it('should respect explicit controller return value when using controllerAs', function() { + module(function() { + directive('main', function() { + return { + templateUrl: 'main.html', + scope: {}, + controller: function() { + this.name = 'lucas'; + return {name: 'george'}; + }, + controllerAs: 'mainCtrl' + }; + }); + }); + inject(function($templateCache, $compile, $rootScope) { + $templateCache.put('main.html', 'template:{{mainCtrl.name}}'); + element = $compile('
')($rootScope); + $rootScope.$apply(); + expect(element.text()).toBe('template:george'); + }); + }); + + + it('transcluded children should receive explicit return value of parent controller', function() { + var expectedController; + module(function() { + directive('nester', valueFn({ + transclude: 'content', + controller: function($transclude) { + this.foo = 'baz'; + expectedController = {transclude:$transclude, foo: 'bar'}; + return expectedController; + }, + link: function(scope, el, attr, ctrl) { + ctrl.transclude(cloneAttach); + function cloneAttach(clone) { + el.append(clone); + } + } + })); + directive('nested', function(log) { + return { + require: '^^nester', + link: function(scope, element, attrs, controller) { + expect(controller).toBe(expectedController); + log('done'); + } + }; + }); + }); + inject(function(log, $compile) { + element = $compile('
')($rootScope); + $rootScope.$apply(); + expect(log).toEqual('done'); + }); + }); + + + it('explicit controller return values are ignored if they are primitives', function() { + module(function() { + directive('logControllerProp', function(log) { + return { + controller: function($scope) { + this.foo = 'baz'; // value *will* be used. + return 'bar'; + }, + link: function(scope, element, attrs, controller) { + log(controller.foo); + } + }; + }); + }); + inject(function(log, $compile, $rootScope) { + element = $compile('')($rootScope); + expect(log).toEqual('baz'); + expect(element.data('$logControllerPropController').foo).toEqual('baz'); + }); + }); + + it('should get required parent controller', function() { module(function() { directive('nested', function(log) { From 732f23eda9262179d8a71d550a5fc564920cabc2 Mon Sep 17 00:00:00 2001 From: Caitlin Potter Date: Tue, 17 Mar 2015 08:17:28 -0400 Subject: [PATCH 129/489] test($compile): make test cases more specific for #11326 --- test/ng/compileSpec.js | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index b30ab8631d9a..613902bd120f 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -4198,45 +4198,56 @@ describe('$compile', function() { it('should respect explicit return value from controller', function() { + var expectedController; module(function() { directive('logControllerProp', function(log) { return { controller: function($scope) { this.foo = 'baz'; // value should not be used. - return {foo: 'bar'}; + return expectedController = {foo: 'bar'}; }, link: function(scope, element, attrs, controller) { - log(controller.foo); + expect(expectedController).toBeDefined(); + expect(controller).toBe(expectedController); + expect(controller.foo).toBe('bar'); + log('done'); } }; }); }); inject(function(log, $compile, $rootScope) { element = $compile('')($rootScope); - expect(log).toEqual('bar'); - expect(element.data('$logControllerPropController').foo).toEqual('bar'); + expect(log).toEqual('done'); + expect(element.data('$logControllerPropController')).toBe(expectedController); }); }); it('should get explicit return value of required parent controller', function() { + var expectedController; module(function() { directive('nested', function(log) { return { require: '^^?nested', controller: function() { - return {foo: 'bar'}; + if (!expectedController) expectedController = {foo: 'bar'}; + return expectedController; }, link: function(scope, element, attrs, controller) { - log(!!controller && controller.foo); + if (element.parent().length) { + expect(expectedController).toBeDefined(); + expect(controller).toBe(expectedController); + expect(controller.foo).toBe('bar'); + log('done'); + } } }; }); }); inject(function(log, $compile, $rootScope) { element = $compile('
')($rootScope); - - expect(log).toEqual('bar; false'); + expect(log).toEqual('done'); + expect(element.data('$nestedController')).toBe(expectedController); }); }); @@ -4268,11 +4279,10 @@ describe('$compile', function() { var expectedController; module(function() { directive('nester', valueFn({ - transclude: 'content', + transclude: true, controller: function($transclude) { this.foo = 'baz'; - expectedController = {transclude:$transclude, foo: 'bar'}; - return expectedController; + return expectedController = {transclude:$transclude, foo: 'bar'}; }, link: function(scope, el, attr, ctrl) { ctrl.transclude(cloneAttach); @@ -4285,6 +4295,7 @@ describe('$compile', function() { return { require: '^^nester', link: function(scope, element, attrs, controller) { + expect(controller).toBeDefined(); expect(controller).toBe(expectedController); log('done'); } @@ -4294,7 +4305,8 @@ describe('$compile', function() { inject(function(log, $compile) { element = $compile('
')($rootScope); $rootScope.$apply(); - expect(log).toEqual('done'); + expect(log.toString()).toBe('done'); + expect(element.data('$nesterController')).toBe(expectedController); }); }); From 890c425d3f3173892902758adc3341fb4b6a57b7 Mon Sep 17 00:00:00 2001 From: jasperSpeicher Date: Thu, 12 Mar 2015 15:12:22 -0700 Subject: [PATCH 130/489] docs(ngRepeat): improve the explanation of keys Closes #11310 --- src/ng/directive/ngRepeat.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ng/directive/ngRepeat.js b/src/ng/directive/ngRepeat.js index f1ffdb68ee5b..04b9726aa9dd 100644 --- a/src/ng/directive/ngRepeat.js +++ b/src/ng/directive/ngRepeat.js @@ -33,8 +33,8 @@ *
...
* ``` * - * You need to be aware that the JavaScript specification does not define what order - * it will return the keys for an object. (To mitigate this in Angular 1.3 the `ngRepeat` directive + * You need to be aware that the JavaScript specification does not define the order of keys + * returned for an object. (To mitigate this in Angular 1.3 the `ngRepeat` directive * used to sort the keys alphabetically.) * * Version 1.4 removed the alphabetic sorting. We now rely on the order returned by the browser From 083d6f17d8e8276cd020ba34c5107e4cf047be06 Mon Sep 17 00:00:00 2001 From: rodneyebanks Date: Fri, 13 Mar 2015 00:01:48 -0500 Subject: [PATCH 131/489] feat(angular.Module): add `decorator` method Closes #11305 Closes #11300 --- src/loader.js | 12 ++++++++++++ test/loaderSpec.js | 2 ++ 2 files changed, 14 insertions(+) diff --git a/src/loader.js b/src/loader.js index 15ab4bcaa172..be4d1c2072c5 100644 --- a/src/loader.js +++ b/src/loader.js @@ -193,6 +193,18 @@ function setupModuleLoader(window) { */ constant: invokeLater('$provide', 'constant', 'unshift'), + /** + * @ngdoc method + * @name angular.Module#decorator + * @module ng + * @param {string} The name of the service to decorate. + * @param {Function} This function will be invoked when the service needs to be + * instantiated and should return the decorated service instance. + * @description + * See {@link auto.$provide#decorator $provide.decorator()}. + */ + decorator: invokeLater('$provide', 'decorator'), + /** * @ngdoc method * @name angular.Module#animation diff --git a/test/loaderSpec.js b/test/loaderSpec.js index 6faa4db91940..1c4d0bb45d84 100644 --- a/test/loaderSpec.js +++ b/test/loaderSpec.js @@ -32,6 +32,7 @@ describe('module loader', function() { var myModule = window.angular.module('my', ['other'], 'config'); expect(myModule. + decorator('dk', 'dv'). provider('sk', 'sv'). factory('fk', 'fv'). service('a', 'aa'). @@ -46,6 +47,7 @@ describe('module loader', function() { expect(myModule.requires).toEqual(['other']); expect(myModule._invokeQueue).toEqual([ ['$provide', 'constant', ['abc', 123]], + ['$provide', 'decorator', ['dk', 'dv']], ['$provide', 'provider', ['sk', 'sv']], ['$provide', 'factory', ['fk', 'fv']], ['$provide', 'service', ['a', 'aa']], From 8be4f954504c3330116f4327395bafd6f87edf1f Mon Sep 17 00:00:00 2001 From: Wesley Cho Date: Mon, 9 Mar 2015 11:12:25 -0700 Subject: [PATCH 132/489] fix($compile): throw error on invalid directive name Directive names must start with a lower case letter. Previously the compiler would quietly fail. This change adds an assertion that fails if this is not the case. Closes #11281 Closes #11109 --- docs/content/error/$compile/baddir.ngdoc | 8 ++++++++ src/ng/compile.js | 9 +++++++++ test/ng/compileSpec.js | 10 ++++++++++ 3 files changed, 27 insertions(+) create mode 100644 docs/content/error/$compile/baddir.ngdoc diff --git a/docs/content/error/$compile/baddir.ngdoc b/docs/content/error/$compile/baddir.ngdoc new file mode 100644 index 000000000000..56ff07a73e55 --- /dev/null +++ b/docs/content/error/$compile/baddir.ngdoc @@ -0,0 +1,8 @@ +@ngdoc error +@name $compile:baddir +@fullName Invalid Directive Name +@description + +This error occurs when the name of a directive is not valid. + +Directives must start with a lowercase character. \ No newline at end of file diff --git a/src/ng/compile.js b/src/ng/compile.js index 9301582e904c..a071fcae56cc 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -790,6 +790,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { return bindings; } + function assertValidDirectiveName(name) { + var letter = name.charAt(0); + if (!letter || letter !== lowercase(letter)) { + throw $compileMinErr('baddir', "Directive name '{0}' is invalid. The first character must be a lowercase letter", name); + } + return name; + } + /** * @ngdoc method * @name $compileProvider#directive @@ -808,6 +816,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { this.directive = function registerDirective(name, directiveFactory) { assertNotHasOwnProperty(name, 'directive'); if (isString(name)) { + assertValidDirectiveName(name); assertArg(directiveFactory, 'directiveFactory'); if (!hasDirectives.hasOwnProperty(name)) { hasDirectives[name] = []; diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index 613902bd120f..b89f1d08312c 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -147,6 +147,7 @@ describe('$compile', function() { describe('configuration', function() { + it('should register a directive', function() { module(function() { directive('div', function(log) { @@ -201,6 +202,15 @@ describe('$compile', function() { }); inject(function($compile) {}); }); + + it('should throw an exception if a directive name starts with a non-lowercase letter', function() { + module(function() { + expect(function() { + directive('BadDirectiveName', function() { }); + }).toThrowMinErr('$compile','baddir', "Directive name 'BadDirectiveName' is invalid. The first character must be a lowercase letter"); + }); + inject(function($compile) {}); + }); }); From 500e3f9265da8065ccb10526f543c562ad65fe45 Mon Sep 17 00:00:00 2001 From: Chirayu Krishnappa Date: Thu, 12 Feb 2015 13:45:25 -0800 Subject: [PATCH 133/489] feat($interpolate): extend interpolation with MessageFormat like syntax For more detailed information refer to this document: https://docs.google.com/a/google.com/document/d/1pbtW2yvtmFBikfRrJd8VAsabiFkKezmYZ_PbgdjQOVU/edit **Example:** ```html {{recipients.length, plural, offset:1 =0 {You gave no gifts} =1 { {{ recipients[0].gender, select, male {You gave him a gift.} female {You gave her a gift.} other {You gave them a gift.} }} } one { {{ recipients[0].gender, select, male {You gave him and one other person a gift.} female {You gave her and one other person a gift.} other {You gave them and one other person a gift.} }} } other {You gave {{recipients[0].gender}} and # other people gifts. } }} ``` This is a SEPARATE module so you MUST include `angular-messageformat.js` or `angular-messageformat.min.js`. In addition, your application module should depend on the "ngMessageFormat" (e.g. angular.module('myApp', ['ngMessageFormat']);) When you use the `ngMessageFormat`, the $interpolate gets overridden with a new service that adds the new MessageFormat behavior. **Syntax differences from MessageFormat:** - MessageFormat directives are always inside `{{ }}` instead of single `{ }`. This ensures a consistent interpolation syntax (else you could interpolate in more than one way and have to pick one based on the features availability for that syntax.) - The first part of such a syntax can be an arbitrary Angular expression instead of a single identifier. - You can nest them as deep as you want. As mentioned earlier, you would use `{{ }}` to start the nested interpolation that may optionally include select/plural extensions. - Only `select` and `plural` keywords are currently recognized. - Quoting support is coming in a future commit. - Positional arguments/placeholders are not supported. They don't make sense in Angular templates anyway (they are only helpful when using API calls from a programming language.) - Redefining of the startSymbol (`{{`) and endSymbol (`}}`) used for interpolation is not yet supported. Closes #11152 --- Gruntfile.js | 8 + angularFiles.js | 9 + docs/content/error/$interpolate/badexpr.ngdoc | 6 + .../content/error/$interpolate/dupvalue.ngdoc | 11 + .../content/error/$interpolate/logicbug.ngdoc | 12 + .../error/$interpolate/nochgmustache.ngdoc | 17 + docs/content/error/$interpolate/reqarg.ngdoc | 12 + .../content/error/$interpolate/reqcomma.ngdoc | 11 + .../error/$interpolate/reqendbrace.ngdoc | 11 + .../error/$interpolate/reqendinterp.ngdoc | 6 + .../error/$interpolate/reqopenbrace.ngdoc | 12 + .../content/error/$interpolate/reqother.ngdoc | 13 + docs/content/error/$interpolate/unknarg.ngdoc | 12 + docs/content/error/$interpolate/unsafe.ngdoc | 10 + .../error/$interpolate/untermstr.ngdoc | 6 + .../error/$interpolate/wantstring.ngdoc | 8 + docs/content/guide/i18n.ngdoc | 112 +++ lib/grunt/utils.js | 4 +- src/ng/interpolate.js | 25 +- src/ngMessageFormat/.jshintrc | 8 + src/ngMessageFormat/messageFormatCommon.js | 77 ++ .../messageFormatInterpolationParts.js | 133 ++++ src/ngMessageFormat/messageFormatParser.js | 521 +++++++++++++ src/ngMessageFormat/messageFormatSelector.js | 119 +++ src/ngMessageFormat/messageFormatService.js | 65 ++ test/ngMessageFormat/messageFormatSpec.js | 699 ++++++++++++++++++ 26 files changed, 1915 insertions(+), 12 deletions(-) create mode 100644 docs/content/error/$interpolate/badexpr.ngdoc create mode 100644 docs/content/error/$interpolate/dupvalue.ngdoc create mode 100644 docs/content/error/$interpolate/logicbug.ngdoc create mode 100644 docs/content/error/$interpolate/nochgmustache.ngdoc create mode 100644 docs/content/error/$interpolate/reqarg.ngdoc create mode 100644 docs/content/error/$interpolate/reqcomma.ngdoc create mode 100644 docs/content/error/$interpolate/reqendbrace.ngdoc create mode 100644 docs/content/error/$interpolate/reqendinterp.ngdoc create mode 100644 docs/content/error/$interpolate/reqopenbrace.ngdoc create mode 100644 docs/content/error/$interpolate/reqother.ngdoc create mode 100644 docs/content/error/$interpolate/unknarg.ngdoc create mode 100644 docs/content/error/$interpolate/unsafe.ngdoc create mode 100644 docs/content/error/$interpolate/untermstr.ngdoc create mode 100644 docs/content/error/$interpolate/wantstring.ngdoc create mode 100644 src/ngMessageFormat/.jshintrc create mode 100644 src/ngMessageFormat/messageFormatCommon.js create mode 100644 src/ngMessageFormat/messageFormatInterpolationParts.js create mode 100644 src/ngMessageFormat/messageFormatParser.js create mode 100644 src/ngMessageFormat/messageFormatSelector.js create mode 100644 src/ngMessageFormat/messageFormatService.js create mode 100644 test/ngMessageFormat/messageFormatSpec.js diff --git a/Gruntfile.js b/Gruntfile.js index 6f33d955b124..1e77eba3d8f3 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -126,6 +126,9 @@ module.exports = function(grunt) { ngLocale: { files: { src: 'src/ngLocale/**/*.js' }, }, + ngMessageFormat: { + files: { src: 'src/ngMessageFormat/**/*.js' }, + }, ngMessages: { files: { src: 'src/ngMessages/**/*.js' }, }, @@ -200,6 +203,10 @@ module.exports = function(grunt) { dest: 'build/angular-resource.js', src: util.wrap(files['angularModules']['ngResource'], 'module') }, + messageformat: { + dest: 'build/angular-messageFormat.js', + src: util.wrap(files['angularModules']['ngMessageFormat'], 'module') + }, messages: { dest: 'build/angular-messages.js', src: util.wrap(files['angularModules']['ngMessages'], 'module') @@ -232,6 +239,7 @@ module.exports = function(grunt) { animate: 'build/angular-animate.js', cookies: 'build/angular-cookies.js', loader: 'build/angular-loader.js', + messageformat: 'build/angular-messageFormat.js', messages: 'build/angular-messages.js', touch: 'build/angular-touch.js', resource: 'build/angular-resource.js', diff --git a/angularFiles.js b/angularFiles.js index 7b8ac77b9b08..bf6d2141a122 100755 --- a/angularFiles.js +++ b/angularFiles.js @@ -94,6 +94,13 @@ var angularFiles = { 'src/ngCookies/cookieStore.js', 'src/ngCookies/cookieWriter.js' ], + 'ngMessageFormat': [ + 'src/ngMessageFormat/messageFormatCommon.js', + 'src/ngMessageFormat/messageFormatSelector.js', + 'src/ngMessageFormat/messageFormatInterpolationParts.js', + 'src/ngMessageFormat/messageFormatParser.js', + 'src/ngMessageFormat/messageFormatService.js' + ], 'ngMessages': [ 'src/ngMessages/messages.js' ], @@ -184,6 +191,7 @@ var angularFiles = { '@angularSrcModules', 'src/ngScenario/browserTrigger.js', 'test/helpers/*.js', + 'test/ngMessageFormat/*.js', 'test/ngMock/*.js', 'test/ngCookies/*.js', 'test/ngRoute/**/*.js', @@ -212,6 +220,7 @@ var angularFiles = { angularFiles['angularSrcModules'] = [].concat( angularFiles['angularModules']['ngAnimate'], + angularFiles['angularModules']['ngMessageFormat'], angularFiles['angularModules']['ngMessages'], angularFiles['angularModules']['ngCookies'], angularFiles['angularModules']['ngResource'], diff --git a/docs/content/error/$interpolate/badexpr.ngdoc b/docs/content/error/$interpolate/badexpr.ngdoc new file mode 100644 index 000000000000..346907c21be2 --- /dev/null +++ b/docs/content/error/$interpolate/badexpr.ngdoc @@ -0,0 +1,6 @@ +@ngdoc error +@name $interpolate:badexpr +@fullName Expecting end operator +@description + +The Angular expression is missing the corresponding closing operator. diff --git a/docs/content/error/$interpolate/dupvalue.ngdoc b/docs/content/error/$interpolate/dupvalue.ngdoc new file mode 100644 index 000000000000..3d72f28e1210 --- /dev/null +++ b/docs/content/error/$interpolate/dupvalue.ngdoc @@ -0,0 +1,11 @@ +@ngdoc error +@name $interpolate:dupvalue +@fullName Duplicate choice in plural/select +@description + +You have repeated a match selection for your plural or select MessageFormat +extension in your interpolation expression. The different choices have to be unique. + +For more information about the MessageFormat syntax in interpolation +expressions, please refer to MessageFormat extensions section at +{@link guide/i18n#MessageFormat Angular i18n MessageFormat} diff --git a/docs/content/error/$interpolate/logicbug.ngdoc b/docs/content/error/$interpolate/logicbug.ngdoc new file mode 100644 index 000000000000..c06d36468911 --- /dev/null +++ b/docs/content/error/$interpolate/logicbug.ngdoc @@ -0,0 +1,12 @@ +@ngdoc error +@name $interpolate:logicbug +@fullName Bug in ngMessageFormat module +@description + +You've just hit a bug in the ngMessageFormat module provided by angular-messageFormat.min.js. +Please file a github issue for this and provide the interpolation text that caused you to hit this +bug mentioning the exact version of AngularJS used and we will fix it! + +For more information about the MessageFormat syntax in interpolation +expressions, please refer to MessageFormat extensions section at +{@link guide/i18n#MessageFormat Angular i18n MessageFormat} diff --git a/docs/content/error/$interpolate/nochgmustache.ngdoc b/docs/content/error/$interpolate/nochgmustache.ngdoc new file mode 100644 index 000000000000..df590dca92aa --- /dev/null +++ b/docs/content/error/$interpolate/nochgmustache.ngdoc @@ -0,0 +1,17 @@ +@ngdoc error +@name $interpolate:nochgmustache +@fullName Redefinition of start/endSymbol incompatible with MessageFormat extensions +@description + +You have redefined `$interpolate.startSymbol`/`$interpolate.endSymbol` and also +loaded the `ngMessageFormat` module (provided by angular-messageFormat.min.js) +while creating your injector. + +`ngMessageFormat` currently does not support redefinition of the +startSymbol/endSymbol used by `$interpolate`. If this is affecting you, please +file an issue and mention @chirayuk on it. This is intended to be fixed in a +future commit and the github issue will help gauge urgency. + +For more information about the MessageFormat syntax in interpolation +expressions, please refer to MessageFormat extensions section at +{@link guide/i18n#MessageFormat Angular i18n MessageFormat} diff --git a/docs/content/error/$interpolate/reqarg.ngdoc b/docs/content/error/$interpolate/reqarg.ngdoc new file mode 100644 index 000000000000..ee6ff2c8ca92 --- /dev/null +++ b/docs/content/error/$interpolate/reqarg.ngdoc @@ -0,0 +1,12 @@ +@ngdoc error +@name $interpolate:reqarg +@fullName Missing required argument for MessageFormat +@description + +You must specify the MessageFormat function that you're using right after the +comma following the Angular expression. Currently, the supported functions are +"plural" and "select" (for gender selections.) + +For more information about the MessageFormat syntax in interpolation +expressions, please refer to MessageFormat extensions section at +{@link guide/i18n#MessageFormat Angular i18n MessageFormat} diff --git a/docs/content/error/$interpolate/reqcomma.ngdoc b/docs/content/error/$interpolate/reqcomma.ngdoc new file mode 100644 index 000000000000..13b137ecc5cd --- /dev/null +++ b/docs/content/error/$interpolate/reqcomma.ngdoc @@ -0,0 +1,11 @@ +@ngdoc error +@name $interpolate:reqcomma +@fullName Missing comma following MessageFormat plural/select keyword +@description + +The MessageFormat syntax requires a comma following the "plural" or "select" +extension keyword in the extended interpolation syntax. + +For more information about the MessageFormat syntax in interpolation +expressions, please refer to MessageFormat extensions section at +{@link guide/i18n#MessageFormat Angular i18n MessageFormat} diff --git a/docs/content/error/$interpolate/reqendbrace.ngdoc b/docs/content/error/$interpolate/reqendbrace.ngdoc new file mode 100644 index 000000000000..a3e765dd698b --- /dev/null +++ b/docs/content/error/$interpolate/reqendbrace.ngdoc @@ -0,0 +1,11 @@ +@ngdoc error +@name $interpolate:reqendbrace +@fullName Unterminated message for plural/select value +@description + +The plural or select message for a value or keyword choice has no matching end +brace to mark the end of the message. + +For more information about the MessageFormat syntax in interpolation +expressions, please refer to MessageFormat extensions section at +{@link guide/i18n#MessageFormat Angular i18n MessageFormat} diff --git a/docs/content/error/$interpolate/reqendinterp.ngdoc b/docs/content/error/$interpolate/reqendinterp.ngdoc new file mode 100644 index 000000000000..f5e78441b7ef --- /dev/null +++ b/docs/content/error/$interpolate/reqendinterp.ngdoc @@ -0,0 +1,6 @@ +@ngdoc error +@name $interpolate:reqendinterp +@fullName Unterminated interpolation +@description + +The interpolation text does not have an ending `endSymbol` ("}}" by default) and is unterminated. diff --git a/docs/content/error/$interpolate/reqopenbrace.ngdoc b/docs/content/error/$interpolate/reqopenbrace.ngdoc new file mode 100644 index 000000000000..6ea091702044 --- /dev/null +++ b/docs/content/error/$interpolate/reqopenbrace.ngdoc @@ -0,0 +1,12 @@ +@ngdoc error +@name $interpolate:reqopenbrace +@fullName An opening brace was expected but not found +@description + +The plural or select extension keyword or values (such as "other", "male", +"female", "=0", "one", "many", etc.) MUST be followed by a message enclosed in +braces. + +For more information about the MessageFormat syntax in interpolation +expressions, please refer to MessageFormat extensions section at +{@link guide/i18n#MessageFormat Angular i18n MessageFormat} diff --git a/docs/content/error/$interpolate/reqother.ngdoc b/docs/content/error/$interpolate/reqother.ngdoc new file mode 100644 index 000000000000..3ed329f893a7 --- /dev/null +++ b/docs/content/error/$interpolate/reqother.ngdoc @@ -0,0 +1,13 @@ +@ngdoc error +@name $interpolate:reqother +@fullName Required choice "other" for select/plural in MessageFormat +@description + +Your interpolation expression with a MessageFormat extension for either +"plural" or "select" (typically used for gender selection) does not contain a +message for the choice "other". Using either select or plural MessageFormat +extensions require that you provide a message for the selection "other". + +For more information about the MessageFormat syntax in interpolation +expressions, please refer to MessageFormat extensions section at +{@link guide/i18n#MessageFormat Angular i18n MessageFormat} diff --git a/docs/content/error/$interpolate/unknarg.ngdoc b/docs/content/error/$interpolate/unknarg.ngdoc new file mode 100644 index 000000000000..313fec6b32db --- /dev/null +++ b/docs/content/error/$interpolate/unknarg.ngdoc @@ -0,0 +1,12 @@ +@ngdoc error +@name $interpolate:unknarg +@fullName Unrecognized MessageFormat extension +@description + +The MessageFormat extensions provided by `ngMessageFormat` are currently +limited to "plural" and "select". The extension that you have used is either +unsupported or invalid. + +For more information about the MessageFormat syntax in interpolation +expressions, please refer to MessageFormat extensions section at +{@link guide/i18n#MessageFormat Angular i18n MessageFormat} diff --git a/docs/content/error/$interpolate/unsafe.ngdoc b/docs/content/error/$interpolate/unsafe.ngdoc new file mode 100644 index 000000000000..bec99dc6a743 --- /dev/null +++ b/docs/content/error/$interpolate/unsafe.ngdoc @@ -0,0 +1,10 @@ +@ngdoc error +@name $interpolate:unsafe +@fullName MessageFormat extensions not allowed in secure context +@description + +You have attempted to use a MessageFormat extension in your interpolation expression that is marked as a secure context. For security purposes, this is not supported. + +Read more about secure contexts at {@link ng.$sce Strict Contextual Escaping +(SCE)} and about the MessageFormat extensions at {@link +guide/i18n#MessageFormat Angular i18n MessageFormat}. diff --git a/docs/content/error/$interpolate/untermstr.ngdoc b/docs/content/error/$interpolate/untermstr.ngdoc new file mode 100644 index 000000000000..4800f46276af --- /dev/null +++ b/docs/content/error/$interpolate/untermstr.ngdoc @@ -0,0 +1,6 @@ +@ngdoc error +@name $interpolate:untermstr +@fullName Unterminated string literal +@description + +The string literal was not terminated in your Angular expression. diff --git a/docs/content/error/$interpolate/wantstring.ngdoc b/docs/content/error/$interpolate/wantstring.ngdoc new file mode 100644 index 000000000000..757efc87dfd2 --- /dev/null +++ b/docs/content/error/$interpolate/wantstring.ngdoc @@ -0,0 +1,8 @@ +@ngdoc error +@name $interpolate:wantstring +@fullName Expected the beginning of a string +@description + +We expected to see the beginning of a string (either a single quote or a double +quote character) in the expression but it was not found. The expression is +invalid. If this is incorrect, please file an issue on github. diff --git a/docs/content/guide/i18n.ngdoc b/docs/content/guide/i18n.ngdoc index 78640feb92c9..c1953260e106 100644 --- a/docs/content/guide/i18n.ngdoc +++ b/docs/content/guide/i18n.ngdoc @@ -137,3 +137,115 @@ The Angular datetime filter uses the time zone settings of the browser. The same application will show different time information depending on the time zone settings of the computer that the application is running on. Neither JavaScript nor Angular currently supports displaying the date with a timezone specified by the developer. + + + +## MessageFormat extensions + +AngularJS interpolations via `$interpolate` and in templates +support an extended syntax based on a subset of the ICU +MessageFormat that covers plurals and gender selections. + +Please refer to our [design doc](https://docs.google.com/a/google.com/document/d/1pbtW2yvtmFBikfRrJd8VAsabiFkKezmYZ_PbgdjQOVU/edit) +for a lot more details. You may find it helpful to play with our [Plnkr Example](http://plnkr.co/edit/QBVRQ70dvKZDWmHW9RyR?p=preview). + +You can read more about the ICU MessageFormat syntax at +[Formatting Messages | ICU User Guide](http://userguide.icu-project.org/formatparse/messages#TOC-MessageFormat). + +This extended syntax is provided by way of the +`ngMessageFormat` module that your application can depend +upon (shipped separately as `angular-messageFormat.min.js` and +`angular-messageFormat.js`.) A current limitation of the +`ngMessageFormat` module, is that it does not support +redefining the `$interpolate` start and end symbols. Only the +default `{{` and `}}` are allowed. + +This syntax extension, while based on MessageFormat, has +been designed to be backwards compatible with existing +AngularJS interpolation expressions. The key rule is simply +this: **All interpolations are done inside double curlies.** +The top level comma operator after an expression inside the +double curlies causes MessageFormat extensions to be +recognized. Such a top level comma is otherwise illegal in +an Angular expression and is used by MessageFormat to +specify the function (such as plural/select) and it's +related syntax. + +To understand the extension, take a look at the ICU +MessageFormat syntax as specified by the ICU documentation. +Anywhere in that MessageFormat that you have regular message +text and you want to substitute an expression, just put it +in double curlies instead of single curlies that +MessageFormat dictates. This has a huge advantage. **You +are no longer limited to simple identifiers for +substitutions**. Because you are using double curlies, you +can stick in any arbitrary interpolation syntax there, +including nesting more MessageFormat expressions! Some +examples will make this clear. In the following example, I +will only be showing you the AngularJS syntax. + + +### Simple plural example + +``` +{{numMessages, plural, + =0 { You have no new messages } + =1 { You have one new message } + other { You have # new messages } +}} +``` + +While I won't be teaching you MessageFormat here, you will +note that the `#` symbol works as expected. You could have +also written it as: + +``` +{{numMessages, plural, + =0 { You have no new messages } + =1 { You have one new message } + other { You have {{numMessages}} new messages } +}} +``` + +where you explicitly typed in `numMessages` for "other" +instead of using `#`. They are nearly the same except if +you're using "offset". Refer to the ICU MessageFormat +documentation to learn about offset. + +Please note that **other** is a **required** category (for +both the plural syntax and the select syntax that is shown +later.) + + +### Simple select (for gender) example + +``` +{{friendGender, select, + male { Invite him } + female { Invite her } + other { Invite them } +}} +``` + +### More complex example that combines some of these + +This is taken from the [plunker example](http://plnkr.co/edit/QBVRQ70dvKZDWmHW9RyR?p=preview) linked to earlier. + +``` +{{recipients.length, plural, offset:1 + =0 {You ({{sender.name}}) gave no gifts} + =1 { {{ recipients[0].gender, select, + male {You ({{sender.name}}) gave him ({{recipients[0].name}}) a gift.} + female {You ({{sender.name}}) gave her ({{recipients[0].name}}) a gift.} + other {You ({{sender.name}}) gave them ({{recipients[0].name}}) a gift.} + }} + } + one { {{ recipients[0].gender, select, + male {You ({{sender.name}}) gave him ({{recipients[0].name}}) and one other person a gift.} + female {You ({{sender.name}}) gave her ({{recipients[0].name}}) and one other person a gift.} + other {You ({{sender.name}}) gave them ({{recipients[0].name}}) and one other person a gift.} + }} + } + other {You ({{sender.name}}) gave {{recipients.length}} people gifts. } +}} +``` diff --git a/lib/grunt/utils.js b/lib/grunt/utils.js index 94610e7d5430..80c97750a284 100644 --- a/lib/grunt/utils.js +++ b/lib/grunt/utils.js @@ -185,6 +185,8 @@ module.exports = { var mapFileName = mapFile.match(/[^\/]+$/)[0]; var errorFileName = file.replace(/\.js$/, '-errors.json'); var versionNumber = grunt.config('NG_VERSION').full; + var compilationLevel = (file === 'build/angular-messageFormat.js') ? + 'ADVANCED_OPTIMIZATIONS' : 'SIMPLE_OPTIMIZATIONS'; shell.exec( 'java ' + this.java32flags() + ' ' + @@ -192,7 +194,7 @@ module.exports = { '-cp bower_components/closure-compiler/compiler.jar' + classPathSep + 'bower_components/ng-closure-runner/ngcompiler.jar ' + 'org.angularjs.closurerunner.NgClosureRunner ' + - '--compilation_level SIMPLE_OPTIMIZATIONS ' + + '--compilation_level ' + compilationLevel + ' ' + '--language_in ECMASCRIPT5_STRICT ' + '--minerr_pass ' + '--minerr_errors ' + errorFileName + ' ' + diff --git a/src/ng/interpolate.js b/src/ng/interpolate.js index b6f38ae9f05c..05dd57af552c 100644 --- a/src/ng/interpolate.js +++ b/src/ng/interpolate.js @@ -1,6 +1,16 @@ 'use strict'; -var $interpolateMinErr = minErr('$interpolate'); +var $interpolateMinErr = angular.$interpolateMinErr = minErr('$interpolate'); +$interpolateMinErr.throwNoconcat = function(text) { + throw $interpolateMinErr('noconcat', + "Error while interpolating: {0}\nStrict Contextual Escaping disallows " + + "interpolations that concatenate multiple expressions when a trusted value is " + + "required. See http://docs.angularjs.org/api/ng.$sce", text); +}; + +$interpolateMinErr.interr = function(text, err) { + return $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, err.toString()); +}; /** * @ngdoc provider @@ -244,10 +254,7 @@ function $InterpolateProvider() { // make it obvious that you bound the value to some user controlled value. This helps reduce // the load when auditing for XSS issues. if (trustedContext && concat.length > 1) { - throw $interpolateMinErr('noconcat', - "Error while interpolating: {0}\nStrict Contextual Escaping disallows " + - "interpolations that concatenate multiple expressions when a trusted value is " + - "required. See http://docs.angularjs.org/api/ng.$sce", text); + $interpolateMinErr.throwNoconcat(text); } if (!mustHaveExpression || expressions.length) { @@ -277,9 +284,7 @@ function $InterpolateProvider() { return compute(values); } catch (err) { - var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, - err.toString()); - $exceptionHandler(newErr); + $exceptionHandler($interpolateMinErr.interr(text, err)); } }, { @@ -304,9 +309,7 @@ function $InterpolateProvider() { value = getValue(value); return allOrNothing && !isDefined(value) ? value : stringify(value); } catch (err) { - var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, - err.toString()); - $exceptionHandler(newErr); + $exceptionHandler($interpolateMinErr.interr(text, err)); } } } diff --git a/src/ngMessageFormat/.jshintrc b/src/ngMessageFormat/.jshintrc new file mode 100644 index 000000000000..a385fbf74a0b --- /dev/null +++ b/src/ngMessageFormat/.jshintrc @@ -0,0 +1,8 @@ +{ + "extends": "../../.jshintrc-base", + "browser": true, + "globals": { + "angular": false, + "goog": false // see src/module_closure.prefix + } +} diff --git a/src/ngMessageFormat/messageFormatCommon.js b/src/ngMessageFormat/messageFormatCommon.js new file mode 100644 index 000000000000..b8870ed4fe57 --- /dev/null +++ b/src/ngMessageFormat/messageFormatCommon.js @@ -0,0 +1,77 @@ +'use strict'; + +// NOTE: ADVANCED_OPTIMIZATIONS mode. +// +// This file is compiled with Closure compiler's ADVANCED_OPTIMIZATIONS flag! Be wary of using +// constructs incompatible with that mode. + +var $interpolateMinErr = angular['$interpolateMinErr']; + +var noop = angular['noop'], + isFunction = angular['isFunction'], + toJson = angular['toJson']; + +function stringify(value) { + if (value == null /* null/undefined */) { return ''; } + switch (typeof value) { + case 'string': return value; + case 'number': return '' + value; + default: return toJson(value); + } +} + +// Convert an index into the string into line/column for use in error messages +// As such, this doesn't have to be efficient. +function indexToLineAndColumn(text, index) { + var lines = text.split(/\n/g); + for (var i=0; i < lines.length; i++) { + var line=lines[i]; + if (index >= line.length) { + index -= line.length; + } else { + return { line: i + 1, column: index + 1 }; + } + } +} +var PARSE_CACHE_FOR_TEXT_LITERALS = Object.create(null); + +function parseTextLiteral(text) { + var cachedFn = PARSE_CACHE_FOR_TEXT_LITERALS[text]; + if (cachedFn != null) { + return cachedFn; + } + function parsedFn(context) { return text; } + parsedFn['$$watchDelegate'] = function watchDelegate(scope, listener, objectEquality) { + var unwatch = scope['$watch'](noop, + function textLiteralWatcher() { + if (isFunction(listener)) { listener.call(null, text, text, scope); } + unwatch(); + }, + objectEquality); + return unwatch; + }; + PARSE_CACHE_FOR_TEXT_LITERALS[text] = parsedFn; + parsedFn.exp = text; // Needed to pretend to be $interpolate for tests copied from interpolateSpec.js + parsedFn.expressions = []; // Require this to call $compile.$$addBindingInfo() which allows Protractor to find elements by binding. + return parsedFn; +} + +function subtractOffset(expressionFn, offset) { + if (offset === 0) { + return expressionFn; + } + function minusOffset(value) { + return (value == void 0) ? value : value - offset; + } + function parsedFn(context) { return minusOffset(expressionFn(context)); } + var unwatch; + parsedFn['$$watchDelegate'] = function watchDelegate(scope, listener, objectEquality) { + unwatch = scope['$watch'](expressionFn, + function pluralExpressionWatchListener(newValue, oldValue) { + if (isFunction(listener)) { listener.call(null, minusOffset(newValue), minusOffset(oldValue), scope); } + }, + objectEquality); + return unwatch; + }; + return parsedFn; +} diff --git a/src/ngMessageFormat/messageFormatInterpolationParts.js b/src/ngMessageFormat/messageFormatInterpolationParts.js new file mode 100644 index 000000000000..0be2386a1d5d --- /dev/null +++ b/src/ngMessageFormat/messageFormatInterpolationParts.js @@ -0,0 +1,133 @@ +'use strict'; + +// NOTE: ADVANCED_OPTIMIZATIONS mode. +// +// This file is compiled with Closure compiler's ADVANCED_OPTIMIZATIONS flag! Be wary of using +// constructs incompatible with that mode. + +/* global $interpolateMinErr: false */ +/* global isFunction: false */ +/* global parseTextLiteral: false */ + +/** + * @constructor + * @private + */ +function InterpolationParts(trustedContext, allOrNothing) { + this.trustedContext = trustedContext; + this.allOrNothing = allOrNothing; + this.textParts = []; + this.expressionFns = []; + this.expressionIndices = []; + this.partialText = ''; + this.concatParts = null; +} + +InterpolationParts.prototype.flushPartialText = function flushPartialText() { + if (this.partialText) { + if (this.concatParts == null) { + this.textParts.push(this.partialText); + } else { + this.textParts.push(this.concatParts.join('')); + this.concatParts = null; + } + this.partialText = ''; + } +}; + +InterpolationParts.prototype.addText = function addText(text) { + if (text.length) { + if (!this.partialText) { + this.partialText = text; + } else if (this.concatParts) { + this.concatParts.push(text); + } else { + this.concatParts = [this.partialText, text]; + } + } +}; + +InterpolationParts.prototype.addExpressionFn = function addExpressionFn(expressionFn) { + this.flushPartialText(); + this.expressionIndices.push(this.textParts.length); + this.expressionFns.push(expressionFn); + this.textParts.push(''); +}; + +InterpolationParts.prototype.getExpressionValues = function getExpressionValues(context) { + var expressionValues = new Array(this.expressionFns.length); + for (var i = 0; i < this.expressionFns.length; i++) { + expressionValues[i] = this.expressionFns[i](context); + } + return expressionValues; +}; + +InterpolationParts.prototype.getResult = function getResult(expressionValues) { + for (var i = 0; i < this.expressionIndices.length; i++) { + var expressionValue = expressionValues[i]; + if (this.allOrNothing && expressionValue === void 0) return; + this.textParts[this.expressionIndices[i]] = expressionValue; + } + return this.textParts.join(''); +}; + + +InterpolationParts.prototype.toParsedFn = function toParsedFn(mustHaveExpression, originalText) { + var self = this; + this.flushPartialText(); + if (mustHaveExpression && this.expressionFns.length === 0) { + return void 0; + } + if (this.textParts.length === 0) { + return parseTextLiteral(''); + } + if (this.trustedContext && this.textParts.length > 1) { + $interpolateMinErr['throwNoconcat'](originalText); + } + if (this.expressionFns.length === 0) { + if (this.textParts.length != 1) { this.errorInParseLogic(); } + return parseTextLiteral(this.textParts[0]); + } + var parsedFn = function(context) { + return self.getResult(self.getExpressionValues(context)); + }; + parsedFn['$$watchDelegate'] = function $$watchDelegate(scope, listener, objectEquality) { + return self.watchDelegate(scope, listener, objectEquality); + }; + + parsedFn.exp = originalText; // Needed to pretend to be $interpolate for tests copied from interpolateSpec.js + parsedFn.expressions = new Array(this.expressionFns.length); // Require this to call $compile.$$addBindingInfo() which allows Protractor to find elements by binding. + for (var i = 0; i < this.expressionFns.length; i++) { + parsedFn.expressions[i] = this.expressionFns[i].exp; + } + + return parsedFn; +}; + +InterpolationParts.prototype.watchDelegate = function watchDelegate(scope, listener, objectEquality) { + var watcher = new InterpolationPartsWatcher(this, scope, listener, objectEquality); + return function() { watcher.cancelWatch(); }; +}; + +function InterpolationPartsWatcher(interpolationParts, scope, listener, objectEquality) { + this.interpolationParts = interpolationParts; + this.scope = scope; + this.previousResult = (void 0); + this.listener = listener; + var self = this; + this.expressionFnsWatcher = scope['$watchGroup'](interpolationParts.expressionFns, function(newExpressionValues, oldExpressionValues) { + self.watchListener(newExpressionValues, oldExpressionValues); + }); +} + +InterpolationPartsWatcher.prototype.watchListener = function watchListener(newExpressionValues, oldExpressionValues) { + var result = this.interpolationParts.getResult(newExpressionValues); + if (isFunction(this.listener)) { + this.listener.call(null, result, newExpressionValues === oldExpressionValues ? result : this.previousResult, this.scope); + } + this.previousResult = result; +}; + +InterpolationPartsWatcher.prototype.cancelWatch = function cancelWatch() { + this.expressionFnsWatcher(); +}; diff --git a/src/ngMessageFormat/messageFormatParser.js b/src/ngMessageFormat/messageFormatParser.js new file mode 100644 index 000000000000..66b94bcba40b --- /dev/null +++ b/src/ngMessageFormat/messageFormatParser.js @@ -0,0 +1,521 @@ +'use strict'; + +// NOTE: ADVANCED_OPTIMIZATIONS mode. +// +// This file is compiled with Closure compiler's ADVANCED_OPTIMIZATIONS flag! Be wary of using +// constructs incompatible with that mode. + +/* global $interpolateMinErr: false */ +/* global indexToLineAndColumn: false */ +/* global InterpolationParts: false */ +/* global PluralMessage: false */ +/* global SelectMessage: false */ +/* global subtractOffset: false */ + +// The params src and dst are exactly one of two types: NestedParserState or MessageFormatParser. +// This function is fully optimized by V8. (inspect via IRHydra or --trace-deopt.) +// The idea behind writing it this way is to avoid repeating oneself. This is the ONE place where +// the parser state that is saved/restored when parsing nested mustaches is specified. +function copyNestedParserState(src, dst) { + dst.expressionFn = src.expressionFn; + dst.expressionMinusOffsetFn = src.expressionMinusOffsetFn; + dst.pluralOffset = src.pluralOffset; + dst.choices = src.choices; + dst.choiceKey = src.choiceKey; + dst.interpolationParts = src.interpolationParts; + dst.ruleChoiceKeyword = src.ruleChoiceKeyword; + dst.msgStartIndex = src.msgStartIndex; + dst.expressionStartIndex = src.expressionStartIndex; +} + +function NestedParserState(parser) { + copyNestedParserState(parser, this); +} + +/** + * @constructor + * @private + */ +function MessageFormatParser(text, startIndex, $parse, pluralCat, stringifier, + mustHaveExpression, trustedContext, allOrNothing) { + this.text = text; + this.index = startIndex || 0; + this.$parse = $parse; + this.pluralCat = pluralCat; + this.stringifier = stringifier; + this.mustHaveExpression = !!mustHaveExpression; + this.trustedContext = trustedContext; + this.allOrNothing = !!allOrNothing; + this.expressionFn = null; + this.expressionMinusOffsetFn = null; + this.pluralOffset = null; + this.choices = null; + this.choiceKey = null; + this.interpolationParts = null; + this.msgStartIndex = null; + this.nestedStateStack = []; + this.parsedFn = null; + this.rule = null; + this.ruleStack = null; + this.ruleChoiceKeyword = null; + this.interpNestLevel = null; + this.expressionStartIndex = null; + this.stringStartIndex = null; + this.stringQuote = null; + this.stringInterestsRe = null; + this.angularOperatorStack = null; + this.textPart = null; +} + +// preserve v8 optimization. +var EMPTY_STATE = new NestedParserState(new MessageFormatParser( + /* text= */ '', /* startIndex= */ 0, /* $parse= */ null, /* pluralCat= */ null, /* stringifier= */ null, + /* mustHaveExpression= */ false, /* trustedContext= */ null, /* allOrNothing */ false)); + +MessageFormatParser.prototype.pushState = function pushState() { + this.nestedStateStack.push(new NestedParserState(this)); + copyNestedParserState(EMPTY_STATE, this); +}; + +MessageFormatParser.prototype.popState = function popState() { + if (this.nestedStateStack.length === 0) { + this.errorInParseLogic(); + } + var previousState = this.nestedStateStack.pop(); + copyNestedParserState(previousState, this); +}; + +// Oh my JavaScript! Who knew you couldn't match a regex at a specific +// location in a string but will always search forward?! +// Apparently you'll be growing this ability via the sticky flag (y) in +// ES6. I'll just to work around you for now. +MessageFormatParser.prototype.matchRe = function matchRe(re, search) { + re.lastIndex = this.index; + var match = re.exec(this.text); + if (match != null && (search === true || (match.index == this.index))) { + this.index = re.lastIndex; + return match; + } + return null; +}; + +MessageFormatParser.prototype.searchRe = function searchRe(re) { + return this.matchRe(re, true); +}; + + +MessageFormatParser.prototype.consumeRe = function consumeRe(re) { + // Without the sticky flag, we can't use the .test() method to consume a + // match at the current index. Instead, we'll use the slower .exec() method + // and verify match.index. + return !!this.matchRe(re); +}; + +// Run through our grammar avoiding deeply nested function call chains. +MessageFormatParser.prototype.run = function run(initialRule) { + this.ruleStack = [initialRule]; + do { + this.rule = this.ruleStack.pop(); + while (this.rule) { + this.rule(); + } + this.assertRuleOrNull(this.rule); + } while (this.ruleStack.length > 0); +}; + +MessageFormatParser.prototype.errorInParseLogic = function errorInParseLogic() { + throw $interpolateMinErr('logicbug', + 'The messageformat parser has encountered an internal error. Please file a github issue against the AngularJS project and provide this message text that triggers the bug. Text: “{0}”', + this.text); +}; + +MessageFormatParser.prototype.assertRuleOrNull = function assertRuleOrNull(rule) { + if (rule === void 0) { + this.errorInParseLogic(); + } +}; + +var NEXT_WORD_RE = /\s*(\w+)\s*/g; +MessageFormatParser.prototype.errorExpecting = function errorExpecting() { + // What was wrong with the syntax? Unsupported type, missing comma, or something else? + var match = this.matchRe(NEXT_WORD_RE), position; + if (match == null) { + position = indexToLineAndColumn(this.text, this.index); + throw $interpolateMinErr('reqarg', + 'Expected one of “plural” or “select” at line {0}, column {1} of text “{2}”', + position.line, position.column, this.text); + } + var word = match[1]; + if (word == "select" || word == "plural") { + position = indexToLineAndColumn(this.text, this.index); + throw $interpolateMinErr('reqcomma', + 'Expected a comma after the keyword “{0}” at line {1}, column {2} of text “{3}”', + word, position.line, position.column, this.text); + } else { + position = indexToLineAndColumn(this.text, this.index); + throw $interpolateMinErr('unknarg', + 'Unsupported keyword “{0}” at line {0}, column {1}. Only “plural” and “select” are currently supported. Text: “{3}”', + word, position.line, position.column, this.text); + } +}; + +var STRING_START_RE = /['"]/g; +MessageFormatParser.prototype.ruleString = function ruleString() { + var match = this.matchRe(STRING_START_RE); + if (match == null) { + var position = indexToLineAndColumn(this.text, this.index); + throw $interpolateMinErr('wantstring', + 'Expected the beginning of a string at line {0}, column {1} in text “{2}”', + position.line, position.column, this.text); + } + this.startStringAtMatch(match); +}; + +MessageFormatParser.prototype.startStringAtMatch = function startStringAtMatch(match) { + this.stringStartIndex = match.index; + this.stringQuote = match[0]; + this.stringInterestsRe = this.stringQuote == "'" ? SQUOTED_STRING_INTEREST_RE : DQUOTED_STRING_INTEREST_RE; + this.rule = this.ruleInsideString; +}; + +var SQUOTED_STRING_INTEREST_RE = /\\(?:\\|'|u[0-9A-Fa-f]{4}|x[0-9A-Fa-f]{2}|[0-7]{3}|\r\n|\n|[\s\S])|'/g; +var DQUOTED_STRING_INTEREST_RE = /\\(?:\\|"|u[0-9A-Fa-f]{4}|x[0-9A-Fa-f]{2}|[0-7]{3}|\r\n|\n|[\s\S])|"/g; +MessageFormatParser.prototype.ruleInsideString = function ruleInsideString() { + var match = this.searchRe(this.stringInterestsRe); + if (match == null) { + var position = indexToLineAndColumn(this.text, this.stringStartIndex); + throw $interpolateMinErr('untermstr', + 'The string beginning at line {0}, column {1} is unterminated in text “{2}”', + position.line, position.column, this.text); + } + var chars = match[0]; + if (match == this.stringQuote) { + this.rule = null; + } +}; + +var PLURAL_OR_SELECT_ARG_TYPE_RE = /\s*(plural|select)\s*,\s*/g; +MessageFormatParser.prototype.rulePluralOrSelect = function rulePluralOrSelect() { + var match = this.searchRe(PLURAL_OR_SELECT_ARG_TYPE_RE); + if (match == null) { + this.errorExpecting(); + } + var argType = match[1]; + switch (argType) { + case "plural": this.rule = this.rulePluralStyle; break; + case "select": this.rule = this.ruleSelectStyle; break; + default: this.errorInParseLogic(); + } +}; + +MessageFormatParser.prototype.rulePluralStyle = function rulePluralStyle() { + this.choices = Object.create(null); + this.ruleChoiceKeyword = this.rulePluralValueOrKeyword; + this.rule = this.rulePluralOffset; +}; + +MessageFormatParser.prototype.ruleSelectStyle = function ruleSelectStyle() { + this.choices = Object.create(null); + this.ruleChoiceKeyword = this.ruleSelectKeyword; + this.rule = this.ruleSelectKeyword; +}; + +var NUMBER_RE = /[0]|(?:[1-9][0-9]*)/g; +var PLURAL_OFFSET_RE = new RegExp("\\s*offset\\s*:\\s*(" + NUMBER_RE.source + ")", "g"); + +MessageFormatParser.prototype.rulePluralOffset = function rulePluralOffset() { + var match = this.matchRe(PLURAL_OFFSET_RE); + this.pluralOffset = (match == null) ? 0 : parseInt(match[1], 10); + this.expressionMinusOffsetFn = subtractOffset(this.expressionFn, this.pluralOffset); + this.rule = this.rulePluralValueOrKeyword; +}; + +MessageFormatParser.prototype.assertChoiceKeyIsNew = function assertChoiceKeyIsNew(choiceKey, index) { + if (this.choices[choiceKey] !== void 0) { + var position = indexToLineAndColumn(this.text, index); + throw $interpolateMinErr('dupvalue', + 'The choice “{0}” is specified more than once. Duplicate key is at line {1}, column {2} in text “{3}”', + choiceKey, position.line, position.column, this.text); + } +}; + +var SELECT_KEYWORD = /\s*(\w+)/g; +MessageFormatParser.prototype.ruleSelectKeyword = function ruleSelectKeyword() { + var match = this.matchRe(SELECT_KEYWORD); + if (match == null) { + this.parsedFn = new SelectMessage(this.expressionFn, this.choices).parsedFn; + this.rule = null; + return; + } + this.choiceKey = match[1]; + this.assertChoiceKeyIsNew(this.choiceKey, match.index); + this.rule = this.ruleMessageText; +}; + +var EXPLICIT_VALUE_OR_KEYWORD_RE = new RegExp("\\s*(?:(?:=(" + NUMBER_RE.source + "))|(\\w+))", "g"); +MessageFormatParser.prototype.rulePluralValueOrKeyword = function rulePluralValueOrKeyword() { + var match = this.matchRe(EXPLICIT_VALUE_OR_KEYWORD_RE); + if (match == null) { + this.parsedFn = new PluralMessage(this.expressionFn, this.choices, this.pluralOffset, this.pluralCat).parsedFn; + this.rule = null; + return; + } + if (match[1] != null) { + this.choiceKey = parseInt(match[1], 10); + } else { + this.choiceKey = match[2]; + } + this.assertChoiceKeyIsNew(this.choiceKey, match.index); + this.rule = this.ruleMessageText; +}; + +var BRACE_OPEN_RE = /\s*{/g; +var BRACE_CLOSE_RE = /}/g; +MessageFormatParser.prototype.ruleMessageText = function ruleMessageText() { + if (!this.consumeRe(BRACE_OPEN_RE)) { + var position = indexToLineAndColumn(this.text, this.index); + throw $interpolateMinErr('reqopenbrace', + 'The plural choice “{0}” must be followed by a message in braces at line {1}, column {2} in text “{3}”', + this.choiceKey, position.line, position.column, this.text); + } + this.msgStartIndex = this.index; + this.interpolationParts = new InterpolationParts(this.trustedContext, this.allOrNothing); + this.rule = this.ruleInInterpolationOrMessageText; +}; + +// Note: Since "\" is used as an escape character, don't allow it to be part of the +// startSymbol/endSymbol when I add the feature to allow them to be redefined. +var INTERP_OR_END_MESSAGE_RE = /\\.|{{|}/g; +var INTERP_OR_PLURALVALUE_OR_END_MESSAGE_RE = /\\.|{{|#|}/g; +var ESCAPE_OR_MUSTACHE_BEGIN_RE = /\\.|{{/g; +MessageFormatParser.prototype.advanceInInterpolationOrMessageText = function advanceInInterpolationOrMessageText() { + var currentIndex = this.index, match, re; + if (this.ruleChoiceKeyword == null) { // interpolation + match = this.searchRe(ESCAPE_OR_MUSTACHE_BEGIN_RE); + if (match == null) { // End of interpolation text. Nothing more to process. + this.textPart = this.text.substring(currentIndex); + this.index = this.text.length; + return null; + } + } else { + match = this.searchRe(this.ruleChoiceKeyword == this.rulePluralValueOrKeyword ? + INTERP_OR_PLURALVALUE_OR_END_MESSAGE_RE : INTERP_OR_END_MESSAGE_RE); + if (match == null) { + var position = indexToLineAndColumn(this.text, this.msgStartIndex); + throw $interpolateMinErr('reqendbrace', + 'The plural/select choice “{0}” message starting at line {1}, column {2} does not have an ending closing brace. Text “{3}”', + this.choiceKey, position.line, position.column, this.text); + } + } + // match is non-null. + var token = match[0]; + this.textPart = this.text.substring(currentIndex, match.index); + return token; +}; + +MessageFormatParser.prototype.ruleInInterpolationOrMessageText = function ruleInInterpolationOrMessageText() { + var currentIndex = this.index; + var token = this.advanceInInterpolationOrMessageText(); + if (token == null) { + // End of interpolation text. Nothing more to process. + this.index = this.text.length; + this.interpolationParts.addText(this.text.substring(currentIndex)); + this.rule = null; + return; + } + if (token[0] == "\\") { + // unescape next character and continue + this.interpolationParts.addText(this.textPart + token[1]); + return; + } + this.interpolationParts.addText(this.textPart); + if (token == "{{") { + this.pushState(); + this.ruleStack.push(this.ruleEndMustacheInInterpolationOrMessage); + this.rule = this.ruleEnteredMustache; + } else if (token == "}") { + this.choices[this.choiceKey] = this.interpolationParts.toParsedFn(this.mustHaveExpression, this.text); + this.rule = this.ruleChoiceKeyword; + } else if (token == "#") { + this.interpolationParts.addExpressionFn(this.expressionMinusOffsetFn); + } else { + this.errorInParseLogic(); + } +}; + +MessageFormatParser.prototype.ruleInterpolate = function ruleInterpolate() { + this.interpolationParts = new InterpolationParts(this.trustedContext, this.allOrNothing); + this.rule = this.ruleInInterpolation; +}; + +MessageFormatParser.prototype.ruleInInterpolation = function ruleInInterpolation() { + var currentIndex = this.index; + var match = this.searchRe(ESCAPE_OR_MUSTACHE_BEGIN_RE); + if (match == null) { + // End of interpolation text. Nothing more to process. + this.index = this.text.length; + this.interpolationParts.addText(this.text.substring(currentIndex)); + this.parsedFn = this.interpolationParts.toParsedFn(this.mustHaveExpression, this.text); + this.rule = null; + return; + } + var token = match[0]; + if (token[0] == "\\") { + // unescape next character and continue + this.interpolationParts.addText(this.text.substring(currentIndex, match.index) + token[1]); + return; + } + this.interpolationParts.addText(this.text.substring(currentIndex, match.index)); + this.pushState(); + this.ruleStack.push(this.ruleInterpolationEndMustache); + this.rule = this.ruleEnteredMustache; +}; + +MessageFormatParser.prototype.ruleInterpolationEndMustache = function ruleInterpolationEndMustache() { + var expressionFn = this.parsedFn; + this.popState(); + this.interpolationParts.addExpressionFn(expressionFn); + this.rule = this.ruleInInterpolation; +}; + +MessageFormatParser.prototype.ruleEnteredMustache = function ruleEnteredMustache() { + this.parsedFn = null; + this.ruleStack.push(this.ruleEndMustache); + this.rule = this.ruleAngularExpression; +}; + +MessageFormatParser.prototype.ruleEndMustacheInInterpolationOrMessage = function ruleEndMustacheInInterpolationOrMessage() { + var expressionFn = this.parsedFn; + this.popState(); + this.interpolationParts.addExpressionFn(expressionFn); + this.rule = this.ruleInInterpolationOrMessageText; +}; + + + +var INTERP_END_RE = /\s*}}/g; +MessageFormatParser.prototype.ruleEndMustache = function ruleEndMustache() { + var match = this.matchRe(INTERP_END_RE); + if (match == null) { + var position = indexToLineAndColumn(this.text, this.index); + throw $interpolateMinErr('reqendinterp', + 'Expecting end of interpolation symbol, “{0}”, at line {1}, column {2} in text “{3}”', + '}}', position.line, position.column, this.text); + } + if (this.parsedFn == null) { + // If we parsed a MessageFormat extension, (e.g. select/plural today, maybe more some other + // day), then the result *has* to be a string and those rules would have already set + // this.parsedFn. If there was no MessageFormat extension, then there is no requirement to + // stringify the result and parsedFn isn't set. We set it here. While we could have set it + // unconditionally when exiting the Angular expression, I intend for us to not just replace + // $interpolate, but also to replace $parse in a future version (so ng-bind can work), and in + // such a case we do not want to unnecessarily stringify something if it's not going to be used + // in a string context. + this.parsedFn = this.$parse(this.expressionFn, this.stringifier); + this.parsedFn.exp = this.expressionFn.exp; // Needed to pretend to be $interpolate for tests copied from interpolateSpec.js + this.parsedFn.expressions = this.expressionFn.expressions; // Require this to call $compile.$$addBindingInfo() which allows Protractor to find elements by binding. + } + this.rule = null; +}; + +MessageFormatParser.prototype.ruleAngularExpression = function ruleAngularExpression() { + this.angularOperatorStack = []; + this.expressionStartIndex = this.index; + this.rule = this.ruleInAngularExpression; +}; + +function getEndOperator(opBegin) { + switch (opBegin) { + case "{": return "}"; + case "[": return "]"; + case "(": return ")"; + default: return null; + } +} + +function getBeginOperator(opEnd) { + switch (opEnd) { + case "}": return "{"; + case "]": return "["; + case ")": return "("; + default: return null; + } +} + +// TODO(chirayu): The interpolation endSymbol must also be accounted for. It +// just so happens that "}" is an operator so it's in the list below. But we +// should support any other type of start/end interpolation symbol. +var INTERESTING_OPERATORS_RE = /[[\]{}()'",]/g; +MessageFormatParser.prototype.ruleInAngularExpression = function ruleInAngularExpression() { + var startIndex = this.index; + var match = this.searchRe(INTERESTING_OPERATORS_RE); + var position; + if (match == null) { + if (this.angularOperatorStack.length === 0) { + // This is the end of the Angular expression so this is actually a + // success. Note that when inside an interpolation, this means we even + // consumed the closing interpolation symbols if they were curlies. This + // is NOT an error at this point but will become an error further up the + // stack when the part that saw the opening curlies is unable to find the + // closing ones. + this.index = this.text.length; + this.expressionFn = this.$parse(this.text.substring(this.expressionStartIndex, this.index)); + // Needed to pretend to be $interpolate for tests copied from interpolateSpec.js + this.expressionFn.exp = this.text.substring(this.expressionStartIndex, this.index); + this.rule = null; + return; + } + var innermostOperator = this.angularOperatorStack[0]; + throw $interpolateMinErr('badexpr', + 'Unexpected end of Angular expression. Expecting operator “{0}” at the end of the text “{1}”', + this.getEndOperator(innermostOperator), this.text); + } + var operator = match[0]; + if (operator == "'" || operator == '"') { + this.ruleStack.push(this.ruleInAngularExpression); + this.startStringAtMatch(match); + return; + } + if (operator == ",") { + if (this.trustedContext) { + position = indexToLineAndColumn(this.text, this.index); + throw $interpolateMinErr('unsafe', + 'Use of select/plural MessageFormat syntax is currently disallowed in a secure context ({0}). At line {1}, column {2} of text “{3}”', + this.trustedContext, position.line, position.column, this.text); + } + // only the top level comma has relevance. + if (this.angularOperatorStack.length === 0) { + // todo: does this need to be trimmed? + this.expressionFn = this.$parse(this.text.substring(this.expressionStartIndex, match.index)); + // Needed to pretend to be $interpolate for tests copied from interpolateSpec.js + this.expressionFn.exp = this.text.substring(this.expressionStartIndex, match.index); + this.rule = null; + this.rule = this.rulePluralOrSelect; + } + return; + } + if (getEndOperator(operator) != null) { + this.angularOperatorStack.unshift(operator); + return; + } + var beginOperator = getBeginOperator(operator); + if (beginOperator == null) { + this.errorInParseLogic(); + } + if (this.angularOperatorStack.length > 0) { + if (beginOperator == this.angularOperatorStack[0]) { + this.angularOperatorStack.shift(); + return; + } + position = indexToLineAndColumn(this.text, this.index); + throw $interpolateMinErr('badexpr', + 'Unexpected operator “{0}” at line {1}, column {2} in text. Was expecting “{3}”. Text: “{4}”', + operator, position.line, position.column, getEndOperator(this.angularOperatorStack[0]), this.text); + } + // We are trying to pop off the operator stack but there really isn't anything to pop off. + this.index = match.index; + this.expressionFn = this.$parse(this.text.substring(this.expressionStartIndex, this.index)); + // Needed to pretend to be $interpolate for tests copied from interpolateSpec.js + this.expressionFn.exp = this.text.substring(this.expressionStartIndex, this.index); + this.rule = null; +}; diff --git a/src/ngMessageFormat/messageFormatSelector.js b/src/ngMessageFormat/messageFormatSelector.js new file mode 100644 index 000000000000..6997354594f3 --- /dev/null +++ b/src/ngMessageFormat/messageFormatSelector.js @@ -0,0 +1,119 @@ +'use strict'; + +// NOTE: ADVANCED_OPTIMIZATIONS mode. +// +// This file is compiled with Closure compiler's ADVANCED_OPTIMIZATIONS flag! Be wary of using +// constructs incompatible with that mode. + +/* global $interpolateMinErr: false */ +/* global isFunction: false */ +/* global noop: false */ + +/** + * @constructor + * @private + */ +function MessageSelectorBase(expressionFn, choices) { + var self = this; + this.expressionFn = expressionFn; + this.choices = choices; + if (choices["other"] === void 0) { + throw $interpolateMinErr('reqother', '“other” is a required option.'); + } + this.parsedFn = function(context) { return self.getResult(context); }; + this.parsedFn['$$watchDelegate'] = function $$watchDelegate(scope, listener, objectEquality) { + return self.watchDelegate(scope, listener, objectEquality); + }; +} + +MessageSelectorBase.prototype.getMessageFn = function getMessageFn(value) { + return this.choices[this.categorizeValue(value)]; +}; + +MessageSelectorBase.prototype.getResult = function getResult(context) { + return this.getMessageFn(this.expressionFn(context))(context); +}; + +MessageSelectorBase.prototype.watchDelegate = function watchDelegate(scope, listener, objectEquality) { + var watchers = new MessageSelectorWatchers(this, scope, listener, objectEquality); + return function() { watchers.cancelWatch(); }; +}; + +/** + * @constructor + * @private + */ +function MessageSelectorWatchers(msgSelector, scope, listener, objectEquality) { + var self = this; + this.scope = scope; + this.msgSelector = msgSelector; + this.listener = listener; + this.objectEquality = objectEquality; + this.lastMessage = void 0; + this.messageFnWatcher = noop; + var expressionFnListener = function(newValue, oldValue) { return self.expressionFnListener(newValue, oldValue); }; + this.expressionFnWatcher = scope['$watch'](msgSelector.expressionFn, expressionFnListener, objectEquality); +} + +MessageSelectorWatchers.prototype.expressionFnListener = function expressionFnListener(newValue, oldValue) { + var self = this; + this.messageFnWatcher(); + var messageFnListener = function(newMessage, oldMessage) { return self.messageFnListener(newMessage, oldMessage); }; + var messageFn = this.msgSelector.getMessageFn(newValue); + this.messageFnWatcher = this.scope['$watch'](messageFn, messageFnListener, this.objectEquality); +}; + +MessageSelectorWatchers.prototype.messageFnListener = function messageFnListener(newMessage, oldMessage) { + if (isFunction(this.listener)) { + this.listener.call(null, newMessage, newMessage === oldMessage ? newMessage : this.lastMessage, this.scope); + } + this.lastMessage = newMessage; +}; + +MessageSelectorWatchers.prototype.cancelWatch = function cancelWatch() { + this.expressionFnWatcher(); + this.messageFnWatcher(); +}; + +/** + * @constructor + * @extends MessageSelectorBase + * @private + */ +function SelectMessage(expressionFn, choices) { + MessageSelectorBase.call(this, expressionFn, choices); +} + +function SelectMessageProto() {} +SelectMessageProto.prototype = MessageSelectorBase.prototype; + +SelectMessage.prototype = new SelectMessageProto(); +SelectMessage.prototype.categorizeValue = function categorizeSelectValue(value) { + return (this.choices[value] !== void 0) ? value : "other"; +}; + +/** + * @constructor + * @extends MessageSelectorBase + * @private + */ +function PluralMessage(expressionFn, choices, offset, pluralCat) { + MessageSelectorBase.call(this, expressionFn, choices); + this.offset = offset; + this.pluralCat = pluralCat; +} + +function PluralMessageProto() {} +PluralMessageProto.prototype = MessageSelectorBase.prototype; + +PluralMessage.prototype = new PluralMessageProto(); +PluralMessage.prototype.categorizeValue = function categorizePluralValue(value) { + if (isNaN(value)) { + return "other"; + } else if (this.choices[value] !== void 0) { + return value; + } else { + var category = this.pluralCat(value - this.offset); + return (this.choices[category] !== void 0) ? category : "other"; + } +}; diff --git a/src/ngMessageFormat/messageFormatService.js b/src/ngMessageFormat/messageFormatService.js new file mode 100644 index 000000000000..104218e1a5ab --- /dev/null +++ b/src/ngMessageFormat/messageFormatService.js @@ -0,0 +1,65 @@ +'use strict'; + +// NOTE: ADVANCED_OPTIMIZATIONS mode. +// +// This file is compiled with Closure compiler's ADVANCED_OPTIMIZATIONS flag! Be wary of using +// constructs incompatible with that mode. + +/* global $interpolateMinErr: false */ +/* global MessageFormatParser: false */ +/* global stringify: false */ + +/** + * @ngdoc module + * @name $$messageFormat + * + * @description + * Angular internal service to recognize MessageFormat extensions in interpolation expressions. + * For more information, see: + * https://docs.google.com/a/google.com/document/d/1pbtW2yvtmFBikfRrJd8VAsabiFkKezmYZ_PbgdjQOVU/edit + */ +function $$MessageFormatProvider() { + this['$get'] = ['$parse', '$locale', '$sce', '$exceptionHandler', function $get( + $parse, $locale, $sce, $exceptionHandler) { + + function getStringifier(trustedContext, allOrNothing, text) { + return function stringifier(value) { + try { + value = trustedContext ? $sce['getTrusted'](trustedContext, value) : $sce['valueOf'](value); + return allOrNothing && (value === void 0) ? value : stringify(value); + } catch (err) { + $exceptionHandler($interpolateMinErr['interr'](text, err)); + } + }; + } + + function interpolate(text, mustHaveExpression, trustedContext, allOrNothing) { + var stringifier = getStringifier(trustedContext, allOrNothing, text); + var parser = new MessageFormatParser(text, 0, $parse, $locale['pluralCat'], stringifier, + mustHaveExpression, trustedContext, allOrNothing); + parser.run(parser.ruleInterpolate); + return parser.parsedFn; + } + + return { + 'interpolate': interpolate + }; + }]; +} + +var $$interpolateDecorator = ['$$messageFormat', '$delegate', function $$interpolateDecorator($$messageFormat, $interpolate) { + if ($interpolate['startSymbol']() != "{{" || $interpolate['endSymbol']() != "}}") { + throw $interpolateMinErr('nochgmustache', 'angular-messageformat.js currently does not allow you to use custom start and end symbols for interpolation.'); + } + var interpolate = $$messageFormat['interpolate']; + interpolate['startSymbol'] = $interpolate['startSymbol']; + interpolate['endSymbol'] = $interpolate['endSymbol']; + return interpolate; +}]; + +// define ngMessageFormat module and register $$MessageFormat service +var module = angular['module']('ngMessageFormat', ['ng']); +module['provider']('$$messageFormat', $$MessageFormatProvider); +module['config'](['$provide', function($provide) { + $provide['decorator']('$interpolate', $$interpolateDecorator); +}]); diff --git a/test/ngMessageFormat/messageFormatSpec.js b/test/ngMessageFormat/messageFormatSpec.js new file mode 100644 index 000000000000..fefe3b1d05da --- /dev/null +++ b/test/ngMessageFormat/messageFormatSpec.js @@ -0,0 +1,699 @@ +'use strict'; + +/* TODO: Add tests for: + • Whitespace preservation in messages. + • Whitespace ignored around syntax except for offset:N. + • Escaping for curlies and the # symbol. + • # symbol value. + • # symbol value when gender is nested inside plural. + • Error with nested # symbol. + • parser error messages. + • caching. + • watched expressions. + • test parsing angular expressions + • test the different regexes + • test the different starting rules +*/ + +describe('$$ngMessageFormat', function() { + describe('core', function() { + var $$messageFormat, $parse, $interpolate, $locale, $rootScope; + + function Person(name, gender) { + this.name = name; + this.gender = gender; + } + + var alice = new Person("Alice", "female"), + bob = new Person("Bob", "male"), + charlie = new Person("Charlie", "male"), + harry = new Person("Harry Potter", "male"); + + function initScope($scope) { + $scope.recipients = [alice, bob, charlie]; + $scope.sender = harry; + } + + beforeEach(module('ngMessageFormat')); + + beforeEach(function() { + inject(['$$messageFormat', '$parse', '$locale', '$interpolate', '$rootScope', function( + messageFormat, parse, locale, interpolate, rootScope) { + $$messageFormat = messageFormat; + $parse = parse; + $interpolate = interpolate; + $locale = locale; + $rootScope = rootScope; + initScope(rootScope); + }]); + }); + + describe('mustache', function() { + function assertMustache(text, expected) { + var parsedFn = $interpolate(text); + expect(parsedFn($rootScope)).toEqual(expected); + } + + it('should suppress falsy objects', function() { + assertMustache("{{undefined}}", ""); + assertMustache("{{null}}", ""); + assertMustache("{{a.b}}", ""); + }); + + it('should jsonify objects', function() { + assertMustache("{{ {} }}", "{}"); + assertMustache("{{ true }}", "true"); + assertMustache("{{ false }}", "false"); + assertMustache("{{ 1 }}", "1"); + assertMustache("{{ '1' }}", "1"); + assertMustache("{{ sender }}", '{"name":"Harry Potter","gender":"male"}'); + }); + + it('should return function that can be called with no context', inject(function($interpolate) { + expect($interpolate("{{sender.name}}")()).toEqual(""); + })); + + describe('watchable', function() { + it('ckck', function() { + var calls = []; + $rootScope.$watch($interpolate("{{::name}}"), function(val) { + calls.push(val); + }); + + $rootScope.$apply(); + expect(calls.length).toBe(1); + + $rootScope.name = "foo"; + $rootScope.$apply(); + expect(calls.length).toBe(2); + expect(calls[1]).toBe('foo'); + + $rootScope.name = "bar"; + $rootScope.$apply(); + expect(calls.length).toBe(2); + }); + + + it('should stop watching strings with no expressions after first execution', function() { + var spy = jasmine.createSpy(); + $rootScope.$watch($$messageFormat.interpolate('foo'), spy); + $rootScope.$digest(); + expect($rootScope.$countWatchers()).toBe(0); + expect(spy).toHaveBeenCalledWith('foo', 'foo', $rootScope); + expect(spy.calls.length).toBe(1); + }); + + it('should stop watching strings with only constant expressions after first execution', function() { + var spy = jasmine.createSpy(); + $rootScope.$watch($$messageFormat.interpolate('foo {{42}}'), spy); + $rootScope.$digest(); + expect($rootScope.$countWatchers()).toBe(0); + expect(spy).toHaveBeenCalledWith('foo 42', 'foo 42', $rootScope); + expect(spy.calls.length).toBe(1); + }); + + + }); + + describe('plural', function() { + it('no interpolation', function() { + var text = "" + + "{{recipients.length, plural,\n" + + " =0 {You gave no gifts}\n" + + " =1 {You gave one person a gift}\n" + + // "=1" should override "one" for exact value. + " one {YOU SHOULD NEVER SEE THIS MESSAGE}\n" + + " other {You gave some people gifts}\n" + + "}}"; + var parsedFn = $interpolate(text); + + $rootScope.recipients.length=2; + expect(parsedFn($rootScope)).toEqual("You gave some people gifts"); + + $rootScope.recipients.length=1; + expect(parsedFn($rootScope)).toEqual("You gave one person a gift"); + + $rootScope.recipients.length=0; + expect(parsedFn($rootScope)).toEqual("You gave no gifts"); + }); + + it('with interpolation', function() { + var text = "" + + "{{recipients.length, plural,\n" + + " =0 {{{sender.name}} gave no gifts}\n" + + " =1 {{{sender.name}} gave one gift to {{recipients[0].name}}}\n" + + // "=1" should override "one" for exact value. + " one {YOU SHOULD NEVER SEE THIS MESSAGE}\n" + + " other {{{sender.name}} gave them a gift}\n" + + "}}"; + var parsedFn = $interpolate(text); + + $rootScope.recipients.length=2; + expect(parsedFn($rootScope)).toEqual("Harry Potter gave them a gift"); + + $rootScope.recipients.length=1; + expect(parsedFn($rootScope)).toEqual("Harry Potter gave one gift to Alice"); + + $rootScope.recipients.length=0; + expect(parsedFn($rootScope)).toEqual("Harry Potter gave no gifts"); + }); + + it('with offset, interpolation, "#" symbol with and without escaping', function() { + var text = "" + + "{{recipients.length, plural, offset:1\n" + + // NOTE: It's nonsensical to use "#" for "=0" with a positive offset. + " =0 {{{sender.name}} gave no gifts (\\#=#)}\n" + + " =1 {{{sender.name}} gave one gift to {{recipients[0].name}} (\\#=#)}\n" + + " one {{{sender.name}} gave {{recipients[0].name}} and one other person a gift (\\#=#)}\n" + + " other {{{sender.name}} gave {{recipients[0].name}} and # other people a gift (\\#=#)}\n" + + "}}"; + var parsedFn = $interpolate(text); + + $rootScope.recipients.length=3; + // "#" should get replaced with the value of "recipients.length - offset" + expect(parsedFn($rootScope)).toEqual("Harry Potter gave Alice and 2 other people a gift (#=2)"); + + $rootScope.recipients.length=2; + expect(parsedFn($rootScope)).toEqual("Harry Potter gave Alice and one other person a gift (#=1)"); + + $rootScope.recipients.length=1; + expect(parsedFn($rootScope)).toEqual("Harry Potter gave one gift to Alice (#=0)"); + + $rootScope.recipients.length=0; + expect(parsedFn($rootScope)).toEqual("Harry Potter gave no gifts (#=-1)"); + }); + }); + + it('nested plural and select', function() { + var text = "" + + "{{recipients.length, plural,\n" + + " =0 {You gave no gifts}\n" + + " =1 {{{recipients[0].gender, select,\n" + + " male {You gave him a gift. -{{sender.name}}}\n" + + " female {You gave her a gift. -{{sender.name}}}\n" + + " other {You gave them a gift. -{{sender.name}}}\n" + + " }}\n" + + " }\n" + + " other {You gave {{recipients.length}} people gifts. -{{sender.name}}}\n" + + "}}"; + var parsedFn = $interpolate(text); + var result = parsedFn($rootScope); + expect(result).toEqual("You gave 3 people gifts. -Harry Potter"); + }); + }); + + describe('interpolate', function() { + function assertInterpolation(text, expected) { + var parsedFn = $$messageFormat.interpolate(text); + expect(parsedFn($rootScope)).toEqual(expected); + } + + it('should interpolate a plain string', function() { + assertInterpolation(" Hello, world! ", " Hello, world! "); + }); + + it('should interpolate a simple expression', function() { + assertInterpolation("Hello, {{sender.name}}!", "Hello, Harry Potter!"); + }); + }); + }); + + + /* NOTE: This describe block includes a copy of interpolateSpec.js to test that + * $$messageFormat.interpolate behaves the same as $interpolate. + * ONLY the following changes have been made. + * - Add beforeEach(module('ngMessageFormat')) at top level of describe() + * - Add extra "}" for it('should not unescape markers within expressions'). Original + * $interpolate has a bug/feature where a "}}" inside a string is also treated as a + * closing symbol. The new service understands the string context and fixes this. + * - All tests for startSymbol/endSymbol have been commented out. The new service does not + * allow you to change them as of now. + * - Instead, I've added tests to assert that we throw an exception if used with redefined + * startSymbol/endSymbol. These tests are listed right in the beginning before the + * others. allow you to change them as of now. + */ + describe('$interpolate', function() { + beforeEach(module('ngMessageFormat')); + + describe('startSymbol', function() { + it('should expose the startSymbol in run phase', inject(function($interpolate) { + expect($interpolate.startSymbol()).toBe('{{'); + })); + describe('redefinition', function() { + beforeEach(module(function($interpolateProvider) { + expect($interpolateProvider.startSymbol()).toBe('{{'); + $interpolateProvider.startSymbol('(('); + })); + it('should not work when the startSymbol is redefined', function() { + expect(function() { + inject(inject(function($interpolate) {})); + }).toThrowMinErr('$interpolate', 'nochgmustache'); + }); + }); + }); + + describe('endSymbol', function() { + it('should expose the endSymbol in run phase', inject(function($interpolate) { + expect($interpolate.endSymbol()).toBe('}}'); + })); + describe('redefinition', function() { + beforeEach(module(function($interpolateProvider) { + expect($interpolateProvider.endSymbol()).toBe('}}'); + $interpolateProvider.endSymbol('))'); + })); + it('should not work when the endSymbol is redefined', function() { + expect(function() { + inject(inject(function($interpolate) {})); + }).toThrowMinErr('$interpolate', 'nochgmustache'); + }); + }); + }); + + it('should return the interpolation object when there are no bindings and textOnly is undefined', + inject(function($interpolate) { + var interpolateFn = $interpolate('some text'); + + expect(interpolateFn.exp).toBe('some text'); + expect(interpolateFn.expressions).toEqual([]); + + expect(interpolateFn({})).toBe('some text'); + })); + + + it('should return undefined when there are no bindings and textOnly is set to true', + inject(function($interpolate) { + expect($interpolate('some text', true)).toBeUndefined(); + })); + + it('should return undefined when there are bindings and strict is set to true', + inject(function($interpolate) { + expect($interpolate('test {{foo}}', false, null, true)({})).toBeUndefined(); + })); + + it('should suppress falsy objects', inject(function($interpolate) { + expect($interpolate('{{undefined}}')({})).toEqual(''); + expect($interpolate('{{null}}')({})).toEqual(''); + expect($interpolate('{{a.b}}')({})).toEqual(''); + })); + + it('should jsonify objects', inject(function($interpolate) { + expect($interpolate('{{ {} }}')({})).toEqual('{}'); + expect($interpolate('{{ true }}')({})).toEqual('true'); + expect($interpolate('{{ false }}')({})).toEqual('false'); + })); + + + it('should return interpolation function', inject(function($interpolate, $rootScope) { + var interpolateFn = $interpolate('Hello {{name}}!'); + + expect(interpolateFn.exp).toBe('Hello {{name}}!'); + expect(interpolateFn.expressions).toEqual(['name']); + + var scope = $rootScope.$new(); + scope.name = 'Bubu'; + + expect(interpolateFn(scope)).toBe('Hello Bubu!'); + })); + + + it('should ignore undefined model', inject(function($interpolate) { + expect($interpolate("Hello {{'World'}}{{foo}}")({})).toBe('Hello World'); + })); + + + it('should interpolate with undefined context', inject(function($interpolate) { + expect($interpolate("Hello, world!{{bloop}}")()).toBe("Hello, world!"); + })); + + describe('watching', function() { + it('should be watchable with any input types', inject(function($interpolate, $rootScope) { + var lastVal; + $rootScope.$watch($interpolate('{{i}}'), function(val) { + lastVal = val; + }); + $rootScope.$apply(); + expect(lastVal).toBe(''); + + $rootScope.i = null; + $rootScope.$apply(); + expect(lastVal).toBe(''); + + $rootScope.i = ''; + $rootScope.$apply(); + expect(lastVal).toBe(''); + + $rootScope.i = 0; + $rootScope.$apply(); + expect(lastVal).toBe('0'); + + $rootScope.i = [0]; + $rootScope.$apply(); + expect(lastVal).toBe('[0]'); + + $rootScope.i = {a: 1, b: 2}; + $rootScope.$apply(); + expect(lastVal).toBe('{"a":1,"b":2}'); + })); + + it('should be watchable with literal values', inject(function($interpolate, $rootScope) { + var lastVal; + $rootScope.$watch($interpolate('{{1}}{{"2"}}{{true}}{{[false]}}{{ {a: 2} }}'), function(val) { + lastVal = val; + }); + $rootScope.$apply(); + expect(lastVal).toBe('12true[false]{"a":2}'); + + expect($rootScope.$countWatchers()).toBe(0); + })); + + it('should respect one-time bindings for each individual expression', inject(function($interpolate, $rootScope) { + var calls = []; + $rootScope.$watch($interpolate('{{::a | limitTo:1}} {{::s}} {{::i | number}}'), function(val) { + calls.push(val); + }); + + $rootScope.$apply(); + expect(calls.length).toBe(1); + + $rootScope.a = [1]; + $rootScope.$apply(); + expect(calls.length).toBe(2); + expect(calls[1]).toBe('[1] '); + + $rootScope.a = [0]; + $rootScope.$apply(); + expect(calls.length).toBe(2); + + $rootScope.i = $rootScope.a = 123; + $rootScope.s = 'str!'; + $rootScope.$apply(); + expect(calls.length).toBe(3); + expect(calls[2]).toBe('[1] str! 123'); + + expect($rootScope.$countWatchers()).toBe(0); + })); + + it('should stop watching strings with no expressions after first execution', + inject(function($interpolate, $rootScope) { + var spy = jasmine.createSpy(); + $rootScope.$watch($interpolate('foo'), spy); + $rootScope.$digest(); + expect($rootScope.$countWatchers()).toBe(0); + expect(spy).toHaveBeenCalledWith('foo', 'foo', $rootScope); + expect(spy.calls.length).toBe(1); + }) + ); + + it('should stop watching strings with only constant expressions after first execution', + inject(function($interpolate, $rootScope) { + var spy = jasmine.createSpy(); + $rootScope.$watch($interpolate('foo {{42}}'), spy); + $rootScope.$digest(); + expect($rootScope.$countWatchers()).toBe(0); + expect(spy).toHaveBeenCalledWith('foo 42', 'foo 42', $rootScope); + expect(spy.calls.length).toBe(1); + }) + ); + }); + + describe('interpolation escaping', function() { + var obj; + beforeEach(function() { + obj = {foo: 'Hello', bar: 'World'}; + }); + + + it('should support escaping interpolation signs', inject(function($interpolate) { + expect($interpolate('{{foo}} \\{\\{bar\\}\\}')(obj)).toBe('Hello {{bar}}'); + expect($interpolate('\\{\\{foo\\}\\} {{bar}}')(obj)).toBe('{{foo}} World'); + })); + + + it('should unescape multiple expressions', inject(function($interpolate) { + expect($interpolate('\\{\\{foo\\}\\}\\{\\{bar\\}\\} {{foo}}')(obj)).toBe('{{foo}}{{bar}} Hello'); + expect($interpolate('{{foo}}\\{\\{foo\\}\\}\\{\\{bar\\}\\}')(obj)).toBe('Hello{{foo}}{{bar}}'); + expect($interpolate('\\{\\{foo\\}\\}{{foo}}\\{\\{bar\\}\\}')(obj)).toBe('{{foo}}Hello{{bar}}'); + expect($interpolate('{{foo}}\\{\\{foo\\}\\}{{bar}}\\{\\{bar\\}\\}{{foo}}')(obj)).toBe('Hello{{foo}}World{{bar}}Hello'); + })); + + + /* + *it('should support escaping custom interpolation start/end symbols', function() { + * module(function($interpolateProvider) { + * $interpolateProvider.startSymbol('[['); + * $interpolateProvider.endSymbol(']]'); + * }); + * inject(function($interpolate) { + * expect($interpolate('[[foo]] \\[\\[bar\\]\\]')(obj)).toBe('Hello [[bar]]'); + * }); + *}); + */ + + + it('should unescape incomplete escaped expressions', inject(function($interpolate) { + expect($interpolate('\\{\\{foo{{foo}}')(obj)).toBe('{{fooHello'); + expect($interpolate('\\}\\}foo{{foo}}')(obj)).toBe('}}fooHello'); + expect($interpolate('foo{{foo}}\\{\\{')(obj)).toBe('fooHello{{'); + expect($interpolate('foo{{foo}}\\}\\}')(obj)).toBe('fooHello}}'); + })); + + + it('should not unescape markers within expressions', inject(function($interpolate) { + expect($interpolate('{{"\\\\{\\\\{Hello, world!\\\\}\\\\}"}}')(obj)).toBe('\\{\\{Hello, world!\\}\\}'); + expect($interpolate('{{"\\{\\{Hello, world!\\}\\}"}}')(obj)).toBe('{{Hello, world!}}'); + expect(function() { + $interpolate('{{\\{\\{foo\\}\\}}}')(obj); + }).toThrowMinErr('$parse', 'lexerr', + 'Lexer Error: Unexpected next character at columns 0-0 [\\] in expression [\\{\\{foo\\}\\}]'); + })); + + + // This test demonstrates that the web-server is responsible for escaping every single instance + // of interpolation start/end markers in an expression which they do not wish to evaluate, + // because AngularJS will not protect them from being evaluated (due to the added complexity + // and maintenance burden of context-sensitive escaping) + it('should evaluate expressions between escaped start/end symbols', inject(function($interpolate) { + expect($interpolate('\\{\\{Hello, {{bar}}!\\}\\}')(obj)).toBe('{{Hello, World!}}'); + })); + }); + + + describe('interpolating in a trusted context', function() { + var sce; + beforeEach(function() { + function log() {} + var fakeLog = {log: log, warn: log, info: log, error: log}; + module(function($provide, $sceProvider) { + $provide.value('$log', fakeLog); + $sceProvider.enabled(true); + }); + inject(['$sce', function($sce) { sce = $sce; }]); + }); + + it('should NOT interpolate non-trusted expressions', inject(function($interpolate, $rootScope) { + var scope = $rootScope.$new(); + scope.foo = "foo"; + + expect(function() { + $interpolate('{{foo}}', true, sce.CSS)(scope); + }).toThrowMinErr('$interpolate', 'interr'); + })); + + it('should NOT interpolate mistyped expressions', inject(function($interpolate, $rootScope) { + var scope = $rootScope.$new(); + scope.foo = sce.trustAsCss("foo"); + + expect(function() { + $interpolate('{{foo}}', true, sce.HTML)(scope); + }).toThrowMinErr('$interpolate', 'interr'); + })); + + it('should interpolate trusted expressions in a regular context', inject(function($interpolate) { + var foo = sce.trustAsCss("foo"); + expect($interpolate('{{foo}}', true)({foo: foo})).toBe('foo'); + })); + + it('should interpolate trusted expressions in a specific trustedContext', inject(function($interpolate) { + var foo = sce.trustAsCss("foo"); + expect($interpolate('{{foo}}', true, sce.CSS)({foo: foo})).toBe('foo'); + })); + + // The concatenation of trusted values does not necessarily result in a trusted value. (For + // instance, you can construct evil JS code by putting together pieces of JS strings that are by + // themselves safe to execute in isolation.) + it('should NOT interpolate trusted expressions with multiple parts', inject(function($interpolate) { + var foo = sce.trustAsCss("foo"); + var bar = sce.trustAsCss("bar"); + expect(function() { + return $interpolate('{{foo}}{{bar}}', true, sce.CSS)({foo: foo, bar: bar}); + }).toThrowMinErr( + "$interpolate", "noconcat", "Error while interpolating: {{foo}}{{bar}}\n" + + "Strict Contextual Escaping disallows interpolations that concatenate multiple " + + "expressions when a trusted value is required. See " + + "http://docs.angularjs.org/api/ng.$sce"); + })); + }); + + +/* + * describe('provider', function() { + * beforeEach(module(function($interpolateProvider) { + * $interpolateProvider.startSymbol('--'); + * $interpolateProvider.endSymbol('--'); + * })); + * + * it('should not get confused with same markers', inject(function($interpolate) { + * expect($interpolate('---').expressions).toEqual([]); + * expect($interpolate('----')({})).toEqual(''); + * expect($interpolate('--1--')({})).toEqual('1'); + * })); + * }); + */ + + describe('parseBindings', function() { + it('should Parse Text With No Bindings', inject(function($interpolate) { + expect($interpolate("a").expressions).toEqual([]); + })); + + it('should Parse Empty Text', inject(function($interpolate) { + expect($interpolate("").expressions).toEqual([]); + })); + + it('should Parse Inner Binding', inject(function($interpolate) { + var interpolateFn = $interpolate("a{{b}}C"), + expressions = interpolateFn.expressions; + expect(expressions).toEqual(['b']); + expect(interpolateFn({b: 123})).toEqual('a123C'); + })); + + it('should Parse Ending Binding', inject(function($interpolate) { + var interpolateFn = $interpolate("a{{b}}"), + expressions = interpolateFn.expressions; + expect(expressions).toEqual(['b']); + expect(interpolateFn({b: 123})).toEqual('a123'); + })); + + it('should Parse Begging Binding', inject(function($interpolate) { + var interpolateFn = $interpolate("{{b}}c"), + expressions = interpolateFn.expressions; + expect(expressions).toEqual(['b']); + expect(interpolateFn({b: 123})).toEqual('123c'); + })); + + it('should Parse Loan Binding', inject(function($interpolate) { + var interpolateFn = $interpolate("{{b}}"), + expressions = interpolateFn.expressions; + expect(expressions).toEqual(['b']); + expect(interpolateFn({b: 123})).toEqual('123'); + })); + + it('should Parse Two Bindings', inject(function($interpolate) { + var interpolateFn = $interpolate("{{b}}{{c}}"), + expressions = interpolateFn.expressions; + expect(expressions).toEqual(['b', 'c']); + expect(interpolateFn({b: 111, c: 222})).toEqual('111222'); + })); + + it('should Parse Two Bindings With Text In Middle', inject(function($interpolate) { + var interpolateFn = $interpolate("{{b}}x{{c}}"), + expressions = interpolateFn.expressions; + expect(expressions).toEqual(['b', 'c']); + expect(interpolateFn({b: 111, c: 222})).toEqual('111x222'); + })); + + it('should Parse Multiline', inject(function($interpolate) { + var interpolateFn = $interpolate('"X\nY{{A\n+B}}C\nD"'), + expressions = interpolateFn.expressions; + expect(expressions).toEqual(['A\n+B']); + expect(interpolateFn({'A': 'aa', 'B': 'bb'})).toEqual('"X\nYaabbC\nD"'); + })); + }); + + + describe('isTrustedContext', function() { + it('should NOT interpolate a multi-part expression when isTrustedContext is true', inject(function($interpolate) { + var isTrustedContext = true; + expect(function() { + $interpolate('constant/{{var}}', true, isTrustedContext); + }).toThrowMinErr( + "$interpolate", "noconcat", "Error while interpolating: constant/{{var}}\nStrict " + + "Contextual Escaping disallows interpolations that concatenate multiple expressions " + + "when a trusted value is required. See http://docs.angularjs.org/api/ng.$sce"); + expect(function() { + $interpolate('{{var}}/constant', true, isTrustedContext); + }).toThrowMinErr( + "$interpolate", "noconcat", "Error while interpolating: {{var}}/constant\nStrict " + + "Contextual Escaping disallows interpolations that concatenate multiple expressions " + + "when a trusted value is required. See http://docs.angularjs.org/api/ng.$sce"); + expect(function() { + $interpolate('{{foo}}{{bar}}', true, isTrustedContext); + }).toThrowMinErr( + "$interpolate", "noconcat", "Error while interpolating: {{foo}}{{bar}}\nStrict " + + "Contextual Escaping disallows interpolations that concatenate multiple expressions " + + "when a trusted value is required. See http://docs.angularjs.org/api/ng.$sce"); + })); + + it('should interpolate a multi-part expression when isTrustedContext is false', inject(function($interpolate) { + expect($interpolate('some/{{id}}')({})).toEqual('some/'); + expect($interpolate('some/{{id}}')({id: 1})).toEqual('some/1'); + expect($interpolate('{{foo}}{{bar}}')({foo: 1, bar: 2})).toEqual('12'); + })); + }); + +/* + * describe('startSymbol', function() { + * + * beforeEach(module(function($interpolateProvider) { + * expect($interpolateProvider.startSymbol()).toBe('{{'); + * $interpolateProvider.startSymbol('(('); + * })); + * + * + * it('should expose the startSymbol in config phase', module(function($interpolateProvider) { + * expect($interpolateProvider.startSymbol()).toBe('(('); + * })); + * + * + * it('should expose the startSymbol in run phase', inject(function($interpolate) { + * expect($interpolate.startSymbol()).toBe('(('); + * })); + * + * + * it('should not get confused by matching start and end symbols', function() { + * module(function($interpolateProvider) { + * $interpolateProvider.startSymbol('--'); + * $interpolateProvider.endSymbol('--'); + * }); + * + * inject(function($interpolate) { + * expect($interpolate('---').expressions).toEqual([]); + * expect($interpolate('----')({})).toEqual(''); + * expect($interpolate('--1--')({})).toEqual('1'); + * }); + * }); + * }); + */ + + +/* + * describe('endSymbol', function() { + * + * beforeEach(module(function($interpolateProvider) { + * expect($interpolateProvider.endSymbol()).toBe('}}'); + * $interpolateProvider.endSymbol('))'); + * })); + * + * + * it('should expose the endSymbol in config phase', module(function($interpolateProvider) { + * expect($interpolateProvider.endSymbol()).toBe('))'); + * })); + * + * + * it('should expose the endSymbol in run phase', inject(function($interpolate) { + * expect($interpolate.endSymbol()).toBe('))'); + * })); + * }); + */ + + }); // end of tests copied from $interpolate +}); From f1261b85855d027a4793d9d09c64d25b328a919c Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Mon, 16 Mar 2015 12:36:53 +0000 Subject: [PATCH 134/489] fix($http): throw error if `success` and `error` methods do not receive a function Closes #11330 Closes #11333 --- src/ng/http.js | 4 ++++ test/ng/httpSpec.js | 56 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/src/ng/http.js b/src/ng/http.js index 95a33ae7a1fb..3a2e06c7474d 100644 --- a/src/ng/http.js +++ b/src/ng/http.js @@ -812,6 +812,8 @@ function $HttpProvider() { } promise.success = function(fn) { + assertArgFn(fn, 'fn'); + promise.then(function(response) { fn(response.data, response.status, response.headers, config); }); @@ -819,6 +821,8 @@ function $HttpProvider() { }; promise.error = function(fn) { + assertArgFn(fn, 'fn'); + promise.then(null, function(response) { fn(response.data, response.status, response.headers, config); }); diff --git a/test/ng/httpSpec.js b/test/ng/httpSpec.js index dbb6290323ae..a858c83c64bc 100644 --- a/test/ng/httpSpec.js +++ b/test/ng/httpSpec.js @@ -434,6 +434,34 @@ describe('$http', function() { var httpPromise = $http({url: '/url', method: 'GET'}); expect(httpPromise.success(callback)).toBe(httpPromise); }); + + + it('should error if the callback is not a function', function() { + expect(function() { + $http({url: '/url', method: 'GET'}).success(); + }).toThrowMinErr('ng', 'areq'); + + expect(function() { + $http({url: '/url', method: 'GET'}).success(undefined); + }).toThrowMinErr('ng', 'areq'); + + expect(function() { + $http({url: '/url', method: 'GET'}).success(null); + }).toThrowMinErr('ng', 'areq'); + + + expect(function() { + $http({url: '/url', method: 'GET'}).success({}); + }).toThrowMinErr('ng', 'areq'); + + expect(function() { + $http({url: '/url', method: 'GET'}).success([]); + }).toThrowMinErr('ng', 'areq'); + + expect(function() { + $http({url: '/url', method: 'GET'}).success('error'); + }).toThrowMinErr('ng', 'areq'); + }); }); @@ -458,6 +486,34 @@ describe('$http', function() { var httpPromise = $http({url: '/url', method: 'GET'}); expect(httpPromise.error(callback)).toBe(httpPromise); }); + + + it('should error if the callback is not a function', function() { + expect(function() { + $http({url: '/url', method: 'GET'}).error(); + }).toThrowMinErr('ng', 'areq'); + + expect(function() { + $http({url: '/url', method: 'GET'}).error(undefined); + }).toThrowMinErr('ng', 'areq'); + + expect(function() { + $http({url: '/url', method: 'GET'}).error(null); + }).toThrowMinErr('ng', 'areq'); + + + expect(function() { + $http({url: '/url', method: 'GET'}).error({}); + }).toThrowMinErr('ng', 'areq'); + + expect(function() { + $http({url: '/url', method: 'GET'}).error([]); + }).toThrowMinErr('ng', 'areq'); + + expect(function() { + $http({url: '/url', method: 'GET'}).error('error'); + }).toThrowMinErr('ng', 'areq'); + }); }); }); From 4c6fda816afc701cdff5da59d247d2b0689bb672 Mon Sep 17 00:00:00 2001 From: Julie Ralph Date: Tue, 17 Mar 2015 09:58:21 -0700 Subject: [PATCH 135/489] chore(ci): make wait_for_browser_provider time out after 2 minutes Before, if something went wrong, wait_for_browser_provider.sh would wait indefinitely, and logs would never get printed. Now, we'll bail early, and get some actual logs on what the problem was. Closes #11350 --- scripts/travis/wait_for_browser_provider.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scripts/travis/wait_for_browser_provider.sh b/scripts/travis/wait_for_browser_provider.sh index 1e8157c2b03a..2258ba797939 100755 --- a/scripts/travis/wait_for_browser_provider.sh +++ b/scripts/travis/wait_for_browser_provider.sh @@ -2,6 +2,14 @@ # Wait for Connect to be ready before exiting +# Time out if we wait for more than 2 minutes, so that we can print logs. +let "counter=0" + while [ ! -f $BROWSER_PROVIDER_READY_FILE ]; do + let "counter++" + if [ $counter -gt 240 ]; then + echo "Timed out after 2 minutes waiting for browser provider ready file" + exit 5 + fi sleep .5 done From d1ef6a6fbceeef52d058d6cc5a69fa75eb2cf9ea Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Fri, 13 Mar 2015 18:30:39 +0100 Subject: [PATCH 136/489] fix(ngAria): handle elements with role="checkbox/menuitemcheckbox" Fixes #11317 Closes #11321 --- src/ngAria/aria.js | 157 ++++++++++++++++++++++------------------ test/ngAria/ariaSpec.js | 18 ++++- 2 files changed, 100 insertions(+), 75 deletions(-) diff --git a/src/ngAria/aria.js b/src/ngAria/aria.js index 91a96979d985..ba8fd3530760 100644 --- a/src/ngAria/aria.js +++ b/src/ngAria/aria.js @@ -211,88 +211,101 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) { restrict: 'A', require: '?ngModel', priority: 200, //Make sure watches are fired after any other directives that affect the ngModel value - link: function(scope, elem, attr, ngModel) { + compile: function(elem, attr) { var shape = getShape(attr, elem); - var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem); - - function ngAriaWatchModelValue() { - return ngModel.$modelValue; - } - - function getRadioReaction() { - if (needsTabIndex) { - needsTabIndex = false; - return function ngAriaRadioReaction(newVal) { - var boolVal = (attr.value == ngModel.$viewValue); - elem.attr('aria-checked', boolVal); - elem.attr('tabindex', 0 - !boolVal); - }; - } else { - return function ngAriaRadioReaction(newVal) { - elem.attr('aria-checked', (attr.value == ngModel.$viewValue)); - }; - } - } - - function ngAriaCheckboxReaction(newVal) { - elem.attr('aria-checked', !ngModel.$isEmpty(ngModel.$viewValue)); - } - switch (shape) { - case 'radio': - case 'checkbox': - if (shouldAttachRole(shape, elem)) { - elem.attr('role', shape); - } - if (shouldAttachAttr('aria-checked', 'ariaChecked', elem)) { - scope.$watch(ngAriaWatchModelValue, shape === 'radio' ? - getRadioReaction() : ngAriaCheckboxReaction); + return { + pre: function(scope, elem, attr, ngModel) { + if (shape === 'checkbox' && attr.type !== 'checkbox') { + //Use the input[checkbox] $isEmpty implementation for elements with checkbox roles + ngModel.$isEmpty = function(value) { + return value === false; + }; } - break; - case 'range': - if (shouldAttachRole(shape, elem)) { - elem.attr('role', 'slider'); + }, + post: function(scope, elem, attr, ngModel) { + var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem); + + function ngAriaWatchModelValue() { + return ngModel.$modelValue; } - if ($aria.config('ariaValue')) { - if (attr.min && !elem.attr('aria-valuemin')) { - elem.attr('aria-valuemin', attr.min); - } - if (attr.max && !elem.attr('aria-valuemax')) { - elem.attr('aria-valuemax', attr.max); - } - if (!elem.attr('aria-valuenow')) { - scope.$watch(ngAriaWatchModelValue, function ngAriaValueNowReaction(newVal) { - elem.attr('aria-valuenow', newVal); - }); + + function getRadioReaction() { + if (needsTabIndex) { + needsTabIndex = false; + return function ngAriaRadioReaction(newVal) { + var boolVal = (attr.value == ngModel.$viewValue); + elem.attr('aria-checked', boolVal); + elem.attr('tabindex', 0 - !boolVal); + }; + } else { + return function ngAriaRadioReaction(newVal) { + elem.attr('aria-checked', (attr.value == ngModel.$viewValue)); + }; } } - break; - case 'multiline': - if (shouldAttachAttr('aria-multiline', 'ariaMultiline', elem)) { - elem.attr('aria-multiline', true); + + function ngAriaCheckboxReaction() { + elem.attr('aria-checked', !ngModel.$isEmpty(ngModel.$viewValue)); } - break; - } - if (needsTabIndex) { - elem.attr('tabindex', 0); - } + switch (shape) { + case 'radio': + case 'checkbox': + if (shouldAttachRole(shape, elem)) { + elem.attr('role', shape); + } + if (shouldAttachAttr('aria-checked', 'ariaChecked', elem)) { + scope.$watch(ngAriaWatchModelValue, shape === 'radio' ? + getRadioReaction() : ngAriaCheckboxReaction); + } + break; + case 'range': + if (shouldAttachRole(shape, elem)) { + elem.attr('role', 'slider'); + } + if ($aria.config('ariaValue')) { + if (attr.min && !elem.attr('aria-valuemin')) { + elem.attr('aria-valuemin', attr.min); + } + if (attr.max && !elem.attr('aria-valuemax')) { + elem.attr('aria-valuemax', attr.max); + } + if (!elem.attr('aria-valuenow')) { + scope.$watch(ngAriaWatchModelValue, function ngAriaValueNowReaction(newVal) { + elem.attr('aria-valuenow', newVal); + }); + } + } + break; + case 'multiline': + if (shouldAttachAttr('aria-multiline', 'ariaMultiline', elem)) { + elem.attr('aria-multiline', true); + } + break; + } - if (ngModel.$validators.required && shouldAttachAttr('aria-required', 'ariaRequired', elem)) { - scope.$watch(function ngAriaRequiredWatch() { - return ngModel.$error.required; - }, function ngAriaRequiredReaction(newVal) { - elem.attr('aria-required', !!newVal); - }); - } + if (needsTabIndex) { + elem.attr('tabindex', 0); + } - if (shouldAttachAttr('aria-invalid', 'ariaInvalid', elem)) { - scope.$watch(function ngAriaInvalidWatch() { - return ngModel.$invalid; - }, function ngAriaInvalidReaction(newVal) { - elem.attr('aria-invalid', !!newVal); - }); - } + if (ngModel.$validators.required && shouldAttachAttr('aria-required', 'ariaRequired', elem)) { + scope.$watch(function ngAriaRequiredWatch() { + return ngModel.$error.required; + }, function ngAriaRequiredReaction(newVal) { + elem.attr('aria-required', !!newVal); + }); + } + + if (shouldAttachAttr('aria-invalid', 'ariaInvalid', elem)) { + scope.$watch(function ngAriaInvalidWatch() { + return ngModel.$invalid; + }, function ngAriaInvalidReaction(newVal) { + elem.attr('aria-invalid', !!newVal); + }); + } + } + }; } }; }]) diff --git a/test/ngAria/ariaSpec.js b/test/ngAria/ariaSpec.js index 8da1f83c7611..e23e3e10d6f5 100644 --- a/test/ngAria/ariaSpec.js +++ b/test/ngAria/ariaSpec.js @@ -155,27 +155,39 @@ describe('$aria', function() { }); it('should attach itself to role="radio"', function() { - scope.$apply("val = 'one'"); - compileElement('
'); + scope.val = 'one'; + compileElement('
'); expect(element.attr('aria-checked')).toBe('true'); + + scope.$apply("val = 'two'"); + expect(element.attr('aria-checked')).toBe('false'); }); it('should attach itself to role="checkbox"', function() { scope.val = true; compileElement('
'); expect(element.attr('aria-checked')).toBe('true'); + + scope.$apply('val = false'); + expect(element.attr('aria-checked')).toBe('false'); }); it('should attach itself to role="menuitemradio"', function() { scope.val = 'one'; - compileElement('
'); + compileElement('
'); expect(element.attr('aria-checked')).toBe('true'); + + scope.$apply("val = 'two'"); + expect(element.attr('aria-checked')).toBe('false'); }); it('should attach itself to role="menuitemcheckbox"', function() { scope.val = true; compileElement('
'); expect(element.attr('aria-checked')).toBe('true'); + + scope.$apply('val = false'); + expect(element.attr('aria-checked')).toBe('false'); }); it('should not attach itself if an aria-checked value is already present', function() { From 2176635c876a29801c4e5e93ac197946cb851e26 Mon Sep 17 00:00:00 2001 From: Julie Ralph Date: Tue, 17 Mar 2015 15:38:11 -0700 Subject: [PATCH 137/489] chore(ci): force travis to print logs after driver provider timeout Travis does not do the after_script step if before_script fails, so wait_for_browser_provider.sh was not printing out logs. Force it to print them manually. --- scripts/travis/wait_for_browser_provider.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/travis/wait_for_browser_provider.sh b/scripts/travis/wait_for_browser_provider.sh index 2258ba797939..53d669b370eb 100755 --- a/scripts/travis/wait_for_browser_provider.sh +++ b/scripts/travis/wait_for_browser_provider.sh @@ -9,6 +9,10 @@ while [ ! -f $BROWSER_PROVIDER_READY_FILE ]; do let "counter++" if [ $counter -gt 240 ]; then echo "Timed out after 2 minutes waiting for browser provider ready file" + # We must manually print logs here because travis will not run + # after_script commands if the failure occurs before the script + # phase. + ./print_logs.sh exit 5 fi sleep .5 From c61fbc1f945ee7e6743fb7de90bf4ef6c4988195 Mon Sep 17 00:00:00 2001 From: Bob Fanger Date: Wed, 18 Mar 2015 11:11:35 +0000 Subject: [PATCH 138/489] feat(ngClass): add support for conditional map within an array. This change allows `ngClass` expressions to have both objects and strings within an array: ```js $scope.classVar = 'nav-item'; $scope.activeVar = true; ``` ```html
``` In this case, the CSS classes that will be added are: 'nav-item' and 'is-active'. Closes #4807 --- src/ng/directive/ngClass.js | 41 +++++++++++++++++++++++--------- test/ng/directive/ngClassSpec.js | 11 +++++++++ 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/ng/directive/ngClass.js b/src/ng/directive/ngClass.js index d96169042f7c..3616c5ebf072 100644 --- a/src/ng/directive/ngClass.js +++ b/src/ng/directive/ngClass.js @@ -96,12 +96,15 @@ function classDirective(name, selector) { } function arrayClasses(classVal) { + var classes = []; if (isArray(classVal)) { - return classVal.join(' ').split(' '); + forEach(classVal, function(v) { + classes = classes.concat(arrayClasses(v)); + }); + return classes; } else if (isString(classVal)) { return classVal.split(' '); } else if (isObject(classVal)) { - var classes = []; forEach(classVal, function(v, k) { if (v) { classes = classes.concat(k.split(' ')); @@ -129,16 +132,18 @@ function classDirective(name, selector) { * 1. If the expression evaluates to a string, the string should be one or more space-delimited class * names. * - * 2. If the expression evaluates to an array, each element of the array should be a string that is - * one or more space-delimited class names. - * - * 3. If the expression evaluates to an object, then for each key-value pair of the + * 2. If the expression evaluates to an object, then for each key-value pair of the * object with a truthy value the corresponding key is used as a class name. * + * 3. If the expression evaluates to an array, each element of the array should either be a string as in + * type 1 or an object as in type 2. This means that you can mix strings and objects together in an array + * to give you more control over what CSS classes appear. See the code below for an example of this. + * + * * The directive won't add duplicate classes if a particular class was already set. * - * When the expression changes, the previously added classes are removed and only then the - * new classes are added. + * When the expression changes, the previously added classes are removed and only then are the + * new classes added. * * @animations * **add** - happens just before the class is applied to the elements @@ -167,10 +172,14 @@ function classDirective(name, selector) {


+
+

Using Array and Map Syntax

+
+ warning (apply "orange" class) .strike { - text-decoration: line-through; + text-decoration: line-through; } .bold { font-weight: bold; @@ -178,6 +187,9 @@ function classDirective(name, selector) { .red { color: red; } + .orange { + color: orange; + } var ps = element.all(by.css('p')); @@ -202,11 +214,18 @@ function classDirective(name, selector) { }); it('array example should have 3 classes', function() { - expect(ps.last().getAttribute('class')).toBe(''); + expect(ps.get(2).getAttribute('class')).toBe(''); element(by.model('style1')).sendKeys('bold'); element(by.model('style2')).sendKeys('strike'); element(by.model('style3')).sendKeys('red'); - expect(ps.last().getAttribute('class')).toBe('bold strike red'); + expect(ps.get(2).getAttribute('class')).toBe('bold strike red'); + }); + + it('array with map example should have 2 classes', function() { + expect(ps.last().getAttribute('class')).toBe(''); + element(by.model('style4')).sendKeys('bold'); + element(by.model('warning')).click(); + expect(ps.last().getAttribute('class')).toBe('bold orange'); }); diff --git a/test/ng/directive/ngClassSpec.js b/test/ng/directive/ngClassSpec.js index 2b174dcc2a91..0967aa5898fa 100644 --- a/test/ng/directive/ngClassSpec.js +++ b/test/ng/directive/ngClassSpec.js @@ -63,6 +63,17 @@ describe('ngClass', function() { expect(element.hasClass('AnotB')).toBeFalsy(); })); + it('should support adding multiple classes via an array mixed with conditionally via a map', inject(function($rootScope, $compile) { + element = $compile('
')($rootScope); + $rootScope.$digest(); + expect(element.hasClass('existing')).toBeTruthy(); + expect(element.hasClass('A')).toBeTruthy(); + expect(element.hasClass('B')).toBeFalsy(); + $rootScope.condition = true; + $rootScope.$digest(); + expect(element.hasClass('B')).toBeTruthy(); + + })); it('should remove classes when the referenced object is the same but its property is changed', inject(function($rootScope, $compile) { From 895554d493ec24617457fb8b99375dd070c1890f Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Thu, 19 Mar 2015 14:24:23 +0000 Subject: [PATCH 139/489] docs(error/ngModel/numfmt): provide documentation for this error See: https://github.com/angular/angular.js/commit/db044c408a7f8082758b96ab739348810c36e15a#commitcomment-7577199 Closes #11157 Closes #11334 --- docs/content/error/ngModel/numfmt.ngdoc | 56 +++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 docs/content/error/ngModel/numfmt.ngdoc diff --git a/docs/content/error/ngModel/numfmt.ngdoc b/docs/content/error/ngModel/numfmt.ngdoc new file mode 100644 index 000000000000..19e50f522ee3 --- /dev/null +++ b/docs/content/error/ngModel/numfmt.ngdoc @@ -0,0 +1,56 @@ +@ngdoc error +@name ngModel:numfmt +@fullName Model is not of type `number` +@description + +The number input directive `` requires the model to be a `number`. + +If the model is something else, this error will be thrown. + +Angular does not set validation errors on the `` in this case +as this error is caused by incorrect application logic and not by bad input from the user. + +If your model does not contain actual numbers then it is up to the application developer +to use a directive that will do the conversion in the `ngModel` `$formatters` and `$parsers` +pipeline. + +## Example + +In this example, our model stores the number as a string, so we provide the `stringToNumber` +directive to convert it into the format the `input[number]` directive expects. + + + + + + + + +
+ {{ x }} : {{ typeOf(x) }} +
+
+ + angular.module('numfmt-error-module', []) + + .run(function($rootScope) { + $rootScope.typeOf = function(value) { + return typeof value; + }; + }) + + .directive('stringToNumber', function() { + return { + require: 'ngModel', + link: function(scope, element, attrs, ngModel) { + ngModel.$parsers.push(function(value) { + return '' + value; + }); + ngModel.$formatters.push(function(value) { + return parseFloat(value, 10); + }); + } + }; + }); + +
\ No newline at end of file From b8b8f57a171039e02c3c0381247c07ab1dda2542 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Thu, 19 Mar 2015 14:26:24 +0000 Subject: [PATCH 140/489] chore(docs): improve error doc layout and linking You can now link to an error by its name, namespace:name or error:namespace:name. For example these would all link to https://docs.angularjs.org/error/$compile/ctreq ``` {@link ctreq} {@link $compile:ctreq} {@link error:$compile:ctreq} ``` --- docs/config/index.js | 10 ++++++++-- docs/config/templates/error.template.html | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/config/index.js b/docs/config/index.js index 37c289a29b41..e95d74ce50ae 100644 --- a/docs/config/index.js +++ b/docs/config/index.js @@ -125,10 +125,16 @@ module.exports = new Package('angularjs', [ }); computeIdsProcessor.idTemplates.push({ - docTypes: ['error', 'errorNamespace'], + docTypes: ['error'], + getId: function(doc) { return 'error:' + doc.namespace + ':' + doc.name; }, + getAliases: function(doc) { return [doc.name, doc.namespace + ':' + doc.name, doc.id]; } + }, + { + docTypes: ['errorNamespace'], getId: function(doc) { return 'error:' + doc.name; }, getAliases: function(doc) { return [doc.id]; } - }); + } + ); }) .config(function(checkAnchorLinksProcessor) { diff --git a/docs/config/templates/error.template.html b/docs/config/templates/error.template.html index 91593d2f30d9..cd68fb9652b8 100644 --- a/docs/config/templates/error.template.html +++ b/docs/config/templates/error.template.html @@ -1,7 +1,7 @@ {% extends "base.template.html" %} {% block content %} -

Error: {$ doc.id $} +

Error: {$ doc.namespace $}:{$ doc.name $}
{$ doc.fullName $}

From 8e75852b2368fdda15f944a82e2aed96f8f247df Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Thu, 19 Mar 2015 14:27:35 +0000 Subject: [PATCH 141/489] docs(input[number]): clarify that model must be of type number The docs also now link through to the error doc, which contains a runnable example of how to work around this restriction. Closes #11157 Closes #11334 --- src/ng/directive/input.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index e59ae067582d..e9b781bcf320 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -587,7 +587,11 @@ var inputType = { * Text input with number validation and transformation. Sets the `number` validation * error if not a valid number. * - * The model must always be a number, otherwise Angular will throw an error. + *
+ * The model must always be of type `number` otherwise Angular will throw an error. + * Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt} + * error docs for more information and an example of how to convert your model if necessary. + *
* * @param {string} ngModel Assignable angular expression to data-bind to. * @param {string=} name Property name of the form under which the control is published. From 68650e0e0b815a69f958e9bff2ccc470e4871351 Mon Sep 17 00:00:00 2001 From: Julie Ralph Date: Wed, 18 Mar 2015 16:23:30 -0700 Subject: [PATCH 142/489] chore(test): bump Protractor version to 2.0.0 --- npm-shrinkwrap.clean.json | 98 ++++- npm-shrinkwrap.json | 755 ++++++++++++++++++++++---------------- package.json | 2 +- 3 files changed, 533 insertions(+), 322 deletions(-) diff --git a/npm-shrinkwrap.clean.json b/npm-shrinkwrap.clean.json index aa126fb54993..09eed0e1929e 100644 --- a/npm-shrinkwrap.clean.json +++ b/npm-shrinkwrap.clean.json @@ -6369,7 +6369,7 @@ } }, "protractor": { - "version": "1.7.0", + "version": "2.0.0", "dependencies": { "request": { "version": "2.36.0", @@ -6387,7 +6387,7 @@ "version": "0.5.2" }, "node-uuid": { - "version": "1.4.2" + "version": "1.4.3" }, "tough-cookie": { "version": "0.12.1", @@ -6456,11 +6456,89 @@ } }, "selenium-webdriver": { - "version": "2.44.0", + "version": "2.45.1", "dependencies": { + "rimraf": { + "version": "2.3.2", + "dependencies": { + "glob": { + "version": "4.5.3", + "dependencies": { + "inflight": { + "version": "1.0.4", + "dependencies": { + "wrappy": { + "version": "1.0.1" + } + } + }, + "inherits": { + "version": "2.0.1" + }, + "minimatch": { + "version": "2.0.4", + "dependencies": { + "brace-expansion": { + "version": "1.1.0", + "dependencies": { + "balanced-match": { + "version": "0.2.0" + }, + "concat-map": { + "version": "0.0.1" + } + } + } + } + }, + "once": { + "version": "1.3.1", + "dependencies": { + "wrappy": { + "version": "1.0.1" + } + } + } + } + } + } + }, "tmp": { "version": "0.0.24" }, + "ws": { + "version": "0.7.1", + "dependencies": { + "options": { + "version": "0.0.6" + }, + "ultron": { + "version": "1.0.1" + }, + "bufferutil": { + "version": "1.0.1", + "dependencies": { + "bindings": { + "version": "1.2.1" + }, + "nan": { + "version": "1.6.2" + } + } + }, + "utf-8-validate": { + "version": "1.0.1", + "dependencies": { + "bindings": { + "version": "1.2.1" + }, + "nan": { + "version": "1.6.2" + } + } + } + } + }, "xml2js": { "version": "0.4.4", "dependencies": { @@ -6468,10 +6546,10 @@ "version": "0.6.1" }, "xmlbuilder": { - "version": "2.6.1", + "version": "2.6.2", "dependencies": { "lodash": { - "version": "3.3.0" + "version": "3.5.0" } } } @@ -6486,7 +6564,7 @@ "version": "1.1.0" }, "jasminewd2": { - "version": "0.0.2" + "version": "0.0.3" }, "jasmine": { "version": "2.1.1", @@ -6536,7 +6614,7 @@ "version": "1.0.0" }, "source-map-support": { - "version": "0.2.9", + "version": "0.2.10", "dependencies": { "source-map": { "version": "0.1.32", @@ -6547,6 +6625,12 @@ } } } + }, + "html-entities": { + "version": "1.1.2" + }, + "accessibility-developer-tools": { + "version": "2.6.0" } } }, diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index d31b6ba9b749..528e69c8e73f 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -7664,153 +7664,154 @@ }, "karma": { "version": "0.12.32", - "from": "karma@canary", + "from": "karma@0.12.32", + "resolved": "https://registry.npmjs.org/karma/-/karma-0.12.32.tgz", "dependencies": { "di": { "version": "0.0.1", - "from": "di@~0.0.1", + "from": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz" }, "socket.io": { "version": "1.3.4", - "from": "socket.io@~1.3.0", + "from": "https://registry.npmjs.org/socket.io/-/socket.io-1.3.4.tgz", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-1.3.4.tgz", "dependencies": { "engine.io": { "version": "1.5.1", - "from": "engine.io@1.5.1", + "from": "https://registry.npmjs.org/engine.io/-/engine.io-1.5.1.tgz", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.5.1.tgz", "dependencies": { "debug": { "version": "1.0.3", - "from": "debug@1.0.3", + "from": "https://registry.npmjs.org/debug/-/debug-1.0.3.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.3.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "ms@0.6.2", + "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } }, "ws": { "version": "0.5.0", - "from": "ws@0.5.0", + "from": "https://registry.npmjs.org/ws/-/ws-0.5.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-0.5.0.tgz", "dependencies": { "nan": { "version": "1.4.3", - "from": "nan@1.4.x", + "from": "https://registry.npmjs.org/nan/-/nan-1.4.3.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-1.4.3.tgz" }, "options": { "version": "0.0.6", - "from": "options@>=0.0.5", + "from": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz" }, "ultron": { "version": "1.0.1", - "from": "ultron@1.0.x", + "from": "https://registry.npmjs.org/ultron/-/ultron-1.0.1.tgz", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.1.tgz" } } }, "engine.io-parser": { "version": "1.2.1", - "from": "engine.io-parser@1.2.1", + "from": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.2.1.tgz", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.2.1.tgz", "dependencies": { "after": { "version": "0.8.1", - "from": "after@0.8.1", + "from": "https://registry.npmjs.org/after/-/after-0.8.1.tgz", "resolved": "https://registry.npmjs.org/after/-/after-0.8.1.tgz" }, "arraybuffer.slice": { "version": "0.0.6", - "from": "arraybuffer.slice@0.0.6", + "from": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz" }, "base64-arraybuffer": { "version": "0.1.2", - "from": "base64-arraybuffer@0.1.2", + "from": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.2.tgz", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.2.tgz" }, "blob": { "version": "0.0.2", - "from": "blob@0.0.2", + "from": "https://registry.npmjs.org/blob/-/blob-0.0.2.tgz", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.2.tgz" }, "has-binary": { "version": "0.1.5", - "from": "has-binary@0.1.5", + "from": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.5.tgz", "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.5.tgz", "dependencies": { "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1", + "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" } } }, "utf8": { "version": "2.0.0", - "from": "utf8@2.0.0", + "from": "https://registry.npmjs.org/utf8/-/utf8-2.0.0.tgz", "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.0.0.tgz" } } }, "base64id": { "version": "0.1.0", - "from": "base64id@0.1.0", + "from": "https://registry.npmjs.org/base64id/-/base64id-0.1.0.tgz", "resolved": "https://registry.npmjs.org/base64id/-/base64id-0.1.0.tgz" } } }, "socket.io-parser": { "version": "2.2.3", - "from": "socket.io-parser@2.2.3", + "from": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.3.tgz", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.3.tgz", "dependencies": { "debug": { "version": "0.7.4", - "from": "debug@0.7.4", + "from": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" }, "json3": { "version": "3.2.6", - "from": "json3@3.2.6", + "from": "https://registry.npmjs.org/json3/-/json3-3.2.6.tgz", "resolved": "https://registry.npmjs.org/json3/-/json3-3.2.6.tgz" }, "component-emitter": { "version": "1.1.2", - "from": "component-emitter@1.1.2", + "from": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz" }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1", + "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" } } }, "socket.io-client": { "version": "1.3.4", - "from": "socket.io-client@1.3.4", + "from": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.3.4.tgz", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.3.4.tgz", "dependencies": { "debug": { "version": "0.7.4", - "from": "debug@0.7.4", + "from": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" }, "engine.io-client": { "version": "1.5.1", - "from": "engine.io-client@1.5.1", + "from": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.5.1.tgz", "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.5.1.tgz", "dependencies": { "has-cors": { "version": "1.0.3", - "from": "has-cors@1.0.3", + "from": "https://registry.npmjs.org/has-cors/-/has-cors-1.0.3.tgz", "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.0.3.tgz", "dependencies": { "global": { @@ -7822,27 +7823,27 @@ }, "ws": { "version": "0.4.31", - "from": "ws@0.4.31", + "from": "https://registry.npmjs.org/ws/-/ws-0.4.31.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-0.4.31.tgz", "dependencies": { "commander": { "version": "0.6.1", - "from": "commander@~0.6.1", + "from": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz" }, "nan": { "version": "0.3.2", - "from": "nan@~0.3.0", + "from": "https://registry.npmjs.org/nan/-/nan-0.3.2.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-0.3.2.tgz" }, "tinycolor": { "version": "0.0.1", - "from": "tinycolor@0.x", + "from": "https://registry.npmjs.org/tinycolor/-/tinycolor-0.0.1.tgz", "resolved": "https://registry.npmjs.org/tinycolor/-/tinycolor-0.0.1.tgz" }, "options": { "version": "0.0.6", - "from": "options@>=0.0.5", + "from": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz" } } @@ -7854,73 +7855,73 @@ }, "engine.io-parser": { "version": "1.2.1", - "from": "engine.io-parser@1.2.1", + "from": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.2.1.tgz", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.2.1.tgz", "dependencies": { "after": { "version": "0.8.1", - "from": "after@0.8.1", + "from": "https://registry.npmjs.org/after/-/after-0.8.1.tgz", "resolved": "https://registry.npmjs.org/after/-/after-0.8.1.tgz" }, "arraybuffer.slice": { "version": "0.0.6", - "from": "arraybuffer.slice@0.0.6", + "from": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz" }, "base64-arraybuffer": { "version": "0.1.2", - "from": "base64-arraybuffer@0.1.2", + "from": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.2.tgz", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.2.tgz" }, "blob": { "version": "0.0.2", - "from": "blob@0.0.2", + "from": "https://registry.npmjs.org/blob/-/blob-0.0.2.tgz", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.2.tgz" }, "has-binary": { "version": "0.1.5", - "from": "has-binary@0.1.5", + "from": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.5.tgz", "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.5.tgz", "dependencies": { "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1", + "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" } } }, "utf8": { "version": "2.0.0", - "from": "utf8@2.0.0", + "from": "https://registry.npmjs.org/utf8/-/utf8-2.0.0.tgz", "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.0.0.tgz" } } }, "debug": { "version": "1.0.4", - "from": "debug@1.0.4", + "from": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "ms@0.6.2", + "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } }, "parseuri": { "version": "0.0.4", - "from": "parseuri@0.0.4", + "from": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.4.tgz", "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.4.tgz", "dependencies": { "better-assert": { "version": "1.0.2", - "from": "better-assert@~1.0.0", + "from": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "dependencies": { "callsite": { "version": "1.0.0", - "from": "callsite@1.0.0", + "from": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz" } } @@ -7929,17 +7930,17 @@ }, "parsejson": { "version": "0.0.1", - "from": "parsejson@0.0.1", + "from": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.1.tgz", "resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.1.tgz", "dependencies": { "better-assert": { "version": "1.0.2", - "from": "better-assert@~1.0.0", + "from": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "dependencies": { "callsite": { "version": "1.0.0", - "from": "callsite@1.0.0", + "from": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz" } } @@ -7948,17 +7949,17 @@ }, "parseqs": { "version": "0.0.2", - "from": "parseqs@0.0.2", + "from": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.2.tgz", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.2.tgz", "dependencies": { "better-assert": { "version": "1.0.2", - "from": "better-assert@~1.0.0", + "from": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "dependencies": { "callsite": { "version": "1.0.0", - "from": "callsite@1.0.0", + "from": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz" } } @@ -7967,56 +7968,56 @@ }, "component-inherit": { "version": "0.0.3", - "from": "component-inherit@0.0.3", + "from": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz" } } }, "component-bind": { "version": "1.0.0", - "from": "component-bind@1.0.0", + "from": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz" }, "component-emitter": { "version": "1.1.2", - "from": "component-emitter@1.1.2", + "from": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz" }, "object-component": { "version": "0.0.3", - "from": "object-component@0.0.3", + "from": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz" }, "has-binary": { "version": "0.1.6", - "from": "has-binary@0.1.6", + "from": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.6.tgz", "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.6.tgz", "dependencies": { "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1", + "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" } } }, "indexof": { "version": "0.0.1", - "from": "indexof@0.0.1", + "from": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz" }, "parseuri": { "version": "0.0.2", - "from": "parseuri@0.0.2", + "from": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.2.tgz", "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.2.tgz", "dependencies": { "better-assert": { "version": "1.0.2", - "from": "better-assert@~1.0.0", + "from": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "dependencies": { "callsite": { "version": "1.0.0", - "from": "callsite@1.0.0", + "from": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz" } } @@ -8025,87 +8026,87 @@ }, "to-array": { "version": "0.1.3", - "from": "to-array@0.1.3", + "from": "https://registry.npmjs.org/to-array/-/to-array-0.1.3.tgz", "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.3.tgz" }, "backo2": { "version": "1.0.2", - "from": "backo2@1.0.2", + "from": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz" } } }, "socket.io-adapter": { "version": "0.3.1", - "from": "socket.io-adapter@0.3.1", + "from": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.3.1.tgz", "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.3.1.tgz", "dependencies": { "debug": { "version": "1.0.2", - "from": "debug@1.0.2", + "from": "https://registry.npmjs.org/debug/-/debug-1.0.2.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.2.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "ms@0.6.2", + "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } }, "socket.io-parser": { "version": "2.2.2", - "from": "socket.io-parser@2.2.2", + "from": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.2.tgz", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.2.tgz", "dependencies": { "debug": { "version": "0.7.4", - "from": "debug@0.7.4", + "from": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" }, "json3": { "version": "3.2.6", - "from": "json3@3.2.6", + "from": "https://registry.npmjs.org/json3/-/json3-3.2.6.tgz", "resolved": "https://registry.npmjs.org/json3/-/json3-3.2.6.tgz" }, "component-emitter": { "version": "1.1.2", - "from": "component-emitter@1.1.2", + "from": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz" }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1", + "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" } } }, "object-keys": { "version": "1.0.1", - "from": "object-keys@1.0.1", + "from": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.1.tgz", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.1.tgz" } } }, "has-binary-data": { "version": "0.1.3", - "from": "has-binary-data@0.1.3", + "from": "https://registry.npmjs.org/has-binary-data/-/has-binary-data-0.1.3.tgz", "resolved": "https://registry.npmjs.org/has-binary-data/-/has-binary-data-0.1.3.tgz", "dependencies": { "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1", + "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" } } }, "debug": { "version": "2.1.0", - "from": "debug@2.1.0", + "from": "https://registry.npmjs.org/debug/-/debug-2.1.0.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.1.0.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "ms@0.6.2", + "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } @@ -8114,27 +8115,27 @@ }, "chokidar": { "version": "1.0.0-rc3", - "from": "chokidar@>=0.8.2", + "from": "https://registry.npmjs.org/chokidar/-/chokidar-1.0.0-rc3.tgz", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.0.0-rc3.tgz", "dependencies": { "anymatch": { "version": "1.1.0", - "from": "anymatch@^1.1.0", + "from": "https://registry.npmjs.org/anymatch/-/anymatch-1.1.0.tgz", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.1.0.tgz", "dependencies": { "minimatch": { "version": "1.0.0", - "from": "minimatch@~1.0.0", + "from": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@2", + "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@~1.0.0", + "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -8143,61 +8144,61 @@ }, "async-each": { "version": "0.1.6", - "from": "async-each@^0.1.5", + "from": "https://registry.npmjs.org/async-each/-/async-each-0.1.6.tgz", "resolved": "https://registry.npmjs.org/async-each/-/async-each-0.1.6.tgz" }, "glob-parent": { "version": "1.0.0", - "from": "glob-parent@^1.0.0", + "from": "https://registry.npmjs.org/glob-parent/-/glob-parent-1.0.0.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-1.0.0.tgz", "dependencies": { "is-glob": { "version": "0.3.0", - "from": "is-glob@^0.3.0", + "from": "https://registry.npmjs.org/is-glob/-/is-glob-0.3.0.tgz", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-0.3.0.tgz" } } }, "is-binary-path": { "version": "1.0.0", - "from": "is-binary-path@^1.0.0", + "from": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.0.tgz", "dependencies": { "binary-extensions": { "version": "1.3.0", - "from": "binary-extensions@^1.0.0", + "from": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.3.0.tgz", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.3.0.tgz" } } }, "readdirp": { "version": "1.3.0", - "from": "readdirp@^1.3.0", + "from": "https://registry.npmjs.org/readdirp/-/readdirp-1.3.0.tgz", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-1.3.0.tgz", "dependencies": { "readable-stream": { "version": "1.0.33", - "from": "readable-stream@~1.0.26-2", + "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@~1.0.0", + "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1", + "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@~0.10.x", + "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@~2.0.1", + "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } @@ -8206,12 +8207,12 @@ }, "fsevents": { "version": "0.3.5", - "from": "fsevents@^0.3.1", + "from": "https://registry.npmjs.org/fsevents/-/fsevents-0.3.5.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-0.3.5.tgz", "dependencies": { "nan": { "version": "1.5.3", - "from": "nan@~1.5.0", + "from": "https://registry.npmjs.org/nan/-/nan-1.5.3.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-1.5.3.tgz" } } @@ -8220,27 +8221,27 @@ }, "glob": { "version": "3.2.11", - "from": "glob@~3.2.7", + "from": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@2", + "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", - "from": "minimatch@0.3", + "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@2", + "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@~1.0.0", + "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -8249,54 +8250,54 @@ }, "minimatch": { "version": "0.2.14", - "from": "minimatch@~0.2", + "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@2", + "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@~1.0.0", + "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "expand-braces": { "version": "0.1.1", - "from": "expand-braces@~0.1.1", + "from": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.1.tgz", "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.1.tgz", "dependencies": { "array-slice": { "version": "0.2.2", - "from": "array-slice@^0.2.2", + "from": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.2.tgz", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.2.tgz" }, "array-uniq": { "version": "1.0.2", - "from": "array-uniq@^1.0.1", + "from": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz" }, "braces": { "version": "0.1.5", - "from": "braces@^0.1.2", + "from": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", "dependencies": { "expand-range": { "version": "0.1.1", - "from": "expand-range@^0.1.0", + "from": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", "dependencies": { "is-number": { "version": "0.1.1", - "from": "is-number@^0.1.1", + "from": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz" }, "repeat-string": { "version": "0.2.2", - "from": "repeat-string@^0.2.2", + "from": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz" } } @@ -8307,49 +8308,49 @@ }, "http-proxy": { "version": "0.10.4", - "from": "http-proxy@~0.10", + "from": "https://registry.npmjs.org/http-proxy/-/http-proxy-0.10.4.tgz", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-0.10.4.tgz", "dependencies": { "pkginfo": { "version": "0.3.0", - "from": "pkginfo@0.3.x", + "from": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.0.tgz", "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.0.tgz" }, "utile": { "version": "0.2.1", - "from": "utile@~0.2.1", + "from": "https://registry.npmjs.org/utile/-/utile-0.2.1.tgz", "resolved": "https://registry.npmjs.org/utile/-/utile-0.2.1.tgz", "dependencies": { "async": { "version": "0.2.10", - "from": "async@~0.2.9", + "from": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "deep-equal": { "version": "1.0.0", - "from": "deep-equal@*", + "from": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.0.tgz", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.0.tgz" }, "i": { "version": "0.3.2", - "from": "i@0.3.x", + "from": "https://registry.npmjs.org/i/-/i-0.3.2.tgz", "resolved": "https://registry.npmjs.org/i/-/i-0.3.2.tgz" }, "mkdirp": { "version": "0.5.0", - "from": "mkdirp@0.x.x", + "from": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "minimist@0.0.8", + "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "ncp": { "version": "0.4.2", - "from": "ncp@0.4.x", + "from": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz" } } @@ -8358,261 +8359,261 @@ }, "optimist": { "version": "0.6.1", - "from": "optimist@~0.6.0", + "from": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "dependencies": { "wordwrap": { "version": "0.0.2", - "from": "wordwrap@~0.0.2", + "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" }, "minimist": { "version": "0.0.10", - "from": "minimist@~0.0.1", + "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } }, "rimraf": { "version": "2.2.8", - "from": "rimraf@~2.2.5", + "from": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" }, "q": { "version": "0.9.7", - "from": "q@~0.9.7", + "from": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz" }, "colors": { "version": "0.6.2", - "from": "colors@~0.6.2", + "from": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz" }, "mime": { "version": "1.2.11", - "from": "mime@~1.2.11", + "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "log4js": { "version": "0.6.22", - "from": "log4js@~0.6.3", + "from": "https://registry.npmjs.org/log4js/-/log4js-0.6.22.tgz", "resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.22.tgz", "dependencies": { "async": { "version": "0.2.10", - "from": "async@~0.2.0", + "from": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "readable-stream": { "version": "1.0.33", - "from": "readable-stream@~1.0.2", + "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@~1.0.0", + "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1", + "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@~0.10.x", + "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@~2.0.1", + "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "semver": { "version": "1.1.4", - "from": "semver@~1.1.4", + "from": "https://registry.npmjs.org/semver/-/semver-1.1.4.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-1.1.4.tgz" } } }, "useragent": { "version": "2.0.10", - "from": "useragent@~2.0.4", + "from": "https://registry.npmjs.org/useragent/-/useragent-2.0.10.tgz", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.0.10.tgz", "dependencies": { "lru-cache": { "version": "2.2.4", - "from": "lru-cache@2.2.x", + "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz" } } }, "graceful-fs": { "version": "2.0.3", - "from": "graceful-fs@~2.0.1", + "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz" }, "connect": { "version": "2.26.6", - "from": "connect@~2.26.0", + "from": "https://registry.npmjs.org/connect/-/connect-2.26.6.tgz", "resolved": "https://registry.npmjs.org/connect/-/connect-2.26.6.tgz", "dependencies": { "basic-auth-connect": { "version": "1.0.0", - "from": "basic-auth-connect@1.0.0", + "from": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz" }, "body-parser": { "version": "1.8.4", - "from": "body-parser@~1.8.4", + "from": "https://registry.npmjs.org/body-parser/-/body-parser-1.8.4.tgz", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.8.4.tgz", "dependencies": { "iconv-lite": { "version": "0.4.4", - "from": "iconv-lite@0.4.4", + "from": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.4.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.4.tgz" }, "on-finished": { "version": "2.1.0", - "from": "on-finished@2.1.0", + "from": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", "dependencies": { "ee-first": { "version": "1.0.5", - "from": "ee-first@1.0.5", + "from": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz" } } }, "raw-body": { "version": "1.3.0", - "from": "raw-body@1.3.0", + "from": "https://registry.npmjs.org/raw-body/-/raw-body-1.3.0.tgz", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.3.0.tgz" } } }, "bytes": { "version": "1.0.0", - "from": "bytes@1.0.0", + "from": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz" }, "cookie": { "version": "0.1.2", - "from": "cookie@0.1.2", + "from": "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz" }, "cookie-parser": { "version": "1.3.4", - "from": "cookie-parser@~1.3.3", + "from": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.4.tgz", "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.4.tgz", "dependencies": { "cookie-signature": { "version": "1.0.6", - "from": "cookie-signature@1.0.6", + "from": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" } } }, "cookie-signature": { "version": "1.0.5", - "from": "cookie-signature@1.0.5", + "from": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.5.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.5.tgz" }, "compression": { "version": "1.1.2", - "from": "compression@~1.1.2", + "from": "https://registry.npmjs.org/compression/-/compression-1.1.2.tgz", "resolved": "https://registry.npmjs.org/compression/-/compression-1.1.2.tgz", "dependencies": { "accepts": { "version": "1.1.4", - "from": "accepts@~1.1.2", + "from": "https://registry.npmjs.org/accepts/-/accepts-1.1.4.tgz", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.1.4.tgz", "dependencies": { "mime-types": { "version": "2.0.9", - "from": "mime-types@~2.0.4", + "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", "dependencies": { "mime-db": { "version": "1.7.0", - "from": "mime-db@~1.7.0", + "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz" } } }, "negotiator": { "version": "0.4.9", - "from": "negotiator@0.4.9", + "from": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz" } } }, "compressible": { "version": "2.0.2", - "from": "compressible@~2.0.1", + "from": "https://registry.npmjs.org/compressible/-/compressible-2.0.2.tgz", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.2.tgz", "dependencies": { "mime-db": { "version": "1.7.0", - "from": "mime-db@>= 1.1.2 < 2", + "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz" } } }, "vary": { "version": "1.0.0", - "from": "vary@~1.0.0", + "from": "https://registry.npmjs.org/vary/-/vary-1.0.0.tgz", "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.0.tgz" } } }, "connect-timeout": { "version": "1.3.0", - "from": "connect-timeout@~1.3.0", + "from": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.3.0.tgz", "resolved": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.3.0.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "ms@0.6.2", + "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } }, "csurf": { "version": "1.6.6", - "from": "csurf@~1.6.2", + "from": "https://registry.npmjs.org/csurf/-/csurf-1.6.6.tgz", "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.6.6.tgz", "dependencies": { "csrf": { "version": "2.0.6", - "from": "csrf@~2.0.5", + "from": "https://registry.npmjs.org/csrf/-/csrf-2.0.6.tgz", "resolved": "https://registry.npmjs.org/csrf/-/csrf-2.0.6.tgz", "dependencies": { "base64-url": { "version": "1.2.1", - "from": "base64-url@1.2.1", + "from": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz" }, "rndm": { "version": "1.1.0", - "from": "rndm@~1.1.0", + "from": "https://registry.npmjs.org/rndm/-/rndm-1.1.0.tgz", "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.1.0.tgz" }, "scmp": { "version": "1.0.0", - "from": "scmp@1.0.0", + "from": "https://registry.npmjs.org/scmp/-/scmp-1.0.0.tgz", "resolved": "https://registry.npmjs.org/scmp/-/scmp-1.0.0.tgz" }, "uid-safe": { "version": "1.1.0", - "from": "uid-safe@~1.1.0", + "from": "https://registry.npmjs.org/uid-safe/-/uid-safe-1.1.0.tgz", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-1.1.0.tgz", "dependencies": { "native-or-bluebird": { "version": "1.1.2", - "from": "native-or-bluebird@~1.1.2", + "from": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.1.2.tgz", "resolved": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.1.2.tgz" } } @@ -8621,17 +8622,17 @@ }, "http-errors": { "version": "1.2.8", - "from": "http-errors@~1.2.8", + "from": "https://registry.npmjs.org/http-errors/-/http-errors-1.2.8.tgz", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.2.8.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@~2.0.1", + "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "statuses": { "version": "1.2.1", - "from": "statuses@1", + "from": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz" } } @@ -8640,165 +8641,165 @@ }, "debug": { "version": "2.0.0", - "from": "debug@~2.0.0", + "from": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "ms@0.6.2", + "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } }, "depd": { "version": "0.4.5", - "from": "depd@0.4.5", + "from": "https://registry.npmjs.org/depd/-/depd-0.4.5.tgz", "resolved": "https://registry.npmjs.org/depd/-/depd-0.4.5.tgz" }, "errorhandler": { "version": "1.2.4", - "from": "errorhandler@~1.2.2", + "from": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.2.4.tgz", "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.2.4.tgz", "dependencies": { "accepts": { "version": "1.1.4", - "from": "accepts@~1.1.3", + "from": "https://registry.npmjs.org/accepts/-/accepts-1.1.4.tgz", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.1.4.tgz", "dependencies": { "mime-types": { "version": "2.0.9", - "from": "mime-types@~2.0.4", + "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", "dependencies": { "mime-db": { "version": "1.7.0", - "from": "mime-db@~1.7.0", + "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz" } } }, "negotiator": { "version": "0.4.9", - "from": "negotiator@0.4.9", + "from": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz" } } }, "escape-html": { "version": "1.0.1", - "from": "escape-html@1.0.1", + "from": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz" } } }, "express-session": { "version": "1.8.2", - "from": "express-session@~1.8.2", + "from": "https://registry.npmjs.org/express-session/-/express-session-1.8.2.tgz", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.8.2.tgz", "dependencies": { "crc": { "version": "3.0.0", - "from": "crc@3.0.0", + "from": "https://registry.npmjs.org/crc/-/crc-3.0.0.tgz", "resolved": "https://registry.npmjs.org/crc/-/crc-3.0.0.tgz" }, "uid-safe": { "version": "1.0.1", - "from": "uid-safe@1.0.1", + "from": "https://registry.npmjs.org/uid-safe/-/uid-safe-1.0.1.tgz", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-1.0.1.tgz", "dependencies": { "mz": { "version": "1.3.0", - "from": "mz@1", + "from": "https://registry.npmjs.org/mz/-/mz-1.3.0.tgz", "resolved": "https://registry.npmjs.org/mz/-/mz-1.3.0.tgz", "dependencies": { "native-or-bluebird": { "version": "1.2.0", - "from": "native-or-bluebird@1", + "from": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.2.0.tgz", "resolved": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.2.0.tgz" }, "thenify": { "version": "3.1.0", - "from": "thenify@3", + "from": "https://registry.npmjs.org/thenify/-/thenify-3.1.0.tgz", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.1.0.tgz" }, "thenify-all": { "version": "1.6.0", - "from": "thenify-all@1", + "from": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz" } } }, "base64-url": { "version": "1.2.1", - "from": "base64-url@1", + "from": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz" } } }, "utils-merge": { "version": "1.0.0", - "from": "utils-merge@1.0.0", + "from": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" } } }, "finalhandler": { "version": "0.2.0", - "from": "finalhandler@0.2.0", + "from": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.2.0.tgz", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.2.0.tgz", "dependencies": { "escape-html": { "version": "1.0.1", - "from": "escape-html@1.0.1", + "from": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz" } } }, "fresh": { "version": "0.2.4", - "from": "fresh@0.2.4", + "from": "https://registry.npmjs.org/fresh/-/fresh-0.2.4.tgz", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.4.tgz" }, "media-typer": { "version": "0.3.0", - "from": "media-typer@0.3.0", + "from": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" }, "method-override": { "version": "2.2.0", - "from": "method-override@~2.2.0", + "from": "https://registry.npmjs.org/method-override/-/method-override-2.2.0.tgz", "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.2.0.tgz", "dependencies": { "methods": { "version": "1.1.0", - "from": "methods@1.1.0", + "from": "https://registry.npmjs.org/methods/-/methods-1.1.0.tgz", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.0.tgz" }, "vary": { "version": "1.0.0", - "from": "vary@~1.0.0", + "from": "https://registry.npmjs.org/vary/-/vary-1.0.0.tgz", "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.0.tgz" } } }, "morgan": { "version": "1.3.2", - "from": "morgan@~1.3.2", + "from": "https://registry.npmjs.org/morgan/-/morgan-1.3.2.tgz", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.3.2.tgz", "dependencies": { "basic-auth": { "version": "1.0.0", - "from": "basic-auth@1.0.0", + "from": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.0.tgz", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.0.tgz" }, "on-finished": { "version": "2.1.0", - "from": "on-finished@2.1.0", + "from": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", "dependencies": { "ee-first": { "version": "1.0.5", - "from": "ee-first@1.0.5", + "from": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz" } } @@ -8807,199 +8808,199 @@ }, "multiparty": { "version": "3.3.2", - "from": "multiparty@3.3.2", + "from": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", "dependencies": { "readable-stream": { "version": "1.1.13", - "from": "readable-stream@~1.1.9", + "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@~1.0.0", + "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1", + "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@~0.10.x", + "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@~2.0.1", + "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "stream-counter": { "version": "0.2.0", - "from": "stream-counter@~0.2.0", + "from": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz" } } }, "on-headers": { "version": "1.0.0", - "from": "on-headers@~1.0.0", + "from": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.0.tgz", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.0.tgz" }, "parseurl": { "version": "1.3.0", - "from": "parseurl@~1.3.0", + "from": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz" }, "qs": { "version": "2.2.4", - "from": "qs@2.2.4", + "from": "https://registry.npmjs.org/qs/-/qs-2.2.4.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-2.2.4.tgz" }, "response-time": { "version": "2.0.1", - "from": "response-time@~2.0.1", + "from": "https://registry.npmjs.org/response-time/-/response-time-2.0.1.tgz", "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.0.1.tgz" }, "serve-favicon": { "version": "2.1.7", - "from": "serve-favicon@~2.1.5", + "from": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.1.7.tgz", "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.1.7.tgz", "dependencies": { "etag": { "version": "1.5.1", - "from": "etag@~1.5.0", + "from": "https://registry.npmjs.org/etag/-/etag-1.5.1.tgz", "resolved": "https://registry.npmjs.org/etag/-/etag-1.5.1.tgz", "dependencies": { "crc": { "version": "3.2.1", - "from": "crc@3.2.1", + "from": "https://registry.npmjs.org/crc/-/crc-3.2.1.tgz", "resolved": "https://registry.npmjs.org/crc/-/crc-3.2.1.tgz" } } }, "ms": { "version": "0.6.2", - "from": "ms@0.6.2", + "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } }, "serve-index": { "version": "1.2.1", - "from": "serve-index@~1.2.1", + "from": "https://registry.npmjs.org/serve-index/-/serve-index-1.2.1.tgz", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.2.1.tgz", "dependencies": { "accepts": { "version": "1.1.4", - "from": "accepts@~1.1.0", + "from": "https://registry.npmjs.org/accepts/-/accepts-1.1.4.tgz", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.1.4.tgz", "dependencies": { "mime-types": { "version": "2.0.9", - "from": "mime-types@~2.0.4", + "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", "dependencies": { "mime-db": { "version": "1.7.0", - "from": "mime-db@~1.7.0", + "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz" } } }, "negotiator": { "version": "0.4.9", - "from": "negotiator@0.4.9", + "from": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz" } } }, "batch": { "version": "0.5.1", - "from": "batch@0.5.1", + "from": "https://registry.npmjs.org/batch/-/batch-0.5.1.tgz", "resolved": "https://registry.npmjs.org/batch/-/batch-0.5.1.tgz" } } }, "serve-static": { "version": "1.6.5", - "from": "serve-static@~1.6.4", + "from": "https://registry.npmjs.org/serve-static/-/serve-static-1.6.5.tgz", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.6.5.tgz", "dependencies": { "escape-html": { "version": "1.0.1", - "from": "escape-html@1.0.1", + "from": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz" }, "send": { "version": "0.9.3", - "from": "send@0.9.3", + "from": "https://registry.npmjs.org/send/-/send-0.9.3.tgz", "resolved": "https://registry.npmjs.org/send/-/send-0.9.3.tgz", "dependencies": { "destroy": { "version": "1.0.3", - "from": "destroy@1.0.3", + "from": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz" }, "etag": { "version": "1.4.0", - "from": "etag@~1.4.0", + "from": "https://registry.npmjs.org/etag/-/etag-1.4.0.tgz", "resolved": "https://registry.npmjs.org/etag/-/etag-1.4.0.tgz", "dependencies": { "crc": { "version": "3.0.0", - "from": "crc@3.0.0", + "from": "https://registry.npmjs.org/crc/-/crc-3.0.0.tgz", "resolved": "https://registry.npmjs.org/crc/-/crc-3.0.0.tgz" } } }, "ms": { "version": "0.6.2", - "from": "ms@0.6.2", + "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" }, "on-finished": { "version": "2.1.0", - "from": "on-finished@2.1.0", + "from": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", "dependencies": { "ee-first": { "version": "1.0.5", - "from": "ee-first@1.0.5", + "from": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz" } } }, "range-parser": { "version": "1.0.2", - "from": "range-parser@~1.0.2", + "from": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz" } } }, "utils-merge": { "version": "1.0.0", - "from": "utils-merge@1.0.0", + "from": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" } } }, "type-is": { "version": "1.5.7", - "from": "type-is@~1.5.2", + "from": "https://registry.npmjs.org/type-is/-/type-is-1.5.7.tgz", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.5.7.tgz", "dependencies": { "mime-types": { "version": "2.0.9", - "from": "mime-types@~2.0.9", + "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", "dependencies": { "mime-db": { "version": "1.7.0", - "from": "mime-db@~1.7.0", + "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz" } } @@ -9008,97 +9009,97 @@ }, "vhost": { "version": "3.0.0", - "from": "vhost@~3.0.0", + "from": "https://registry.npmjs.org/vhost/-/vhost-3.0.0.tgz", "resolved": "https://registry.npmjs.org/vhost/-/vhost-3.0.0.tgz" }, "pause": { "version": "0.0.1", - "from": "pause@0.0.1", + "from": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz" } } }, "source-map": { "version": "0.1.43", - "from": "source-map@~0.1.31", + "from": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "amdefine@>=0.0.4", + "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } }, "memoizee": { "version": "0.3.8", - "from": "memoizee@~0.3.8", + "from": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.8.tgz", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.8.tgz", "dependencies": { "d": { "version": "0.1.1", - "from": "d@~0.1.1", + "from": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz" }, "es5-ext": { "version": "0.10.6", - "from": "es5-ext@~0.10.4", + "from": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.6.tgz", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.6.tgz", "dependencies": { "es6-iterator": { "version": "0.1.3", - "from": "es6-iterator@~0.1.3", + "from": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz" }, "es6-symbol": { "version": "2.0.1", - "from": "es6-symbol@~2.0.1", + "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz" } } }, "es6-weak-map": { "version": "0.1.2", - "from": "es6-weak-map@~0.1.2", + "from": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.2.tgz", "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.2.tgz", "dependencies": { "es6-iterator": { "version": "0.1.3", - "from": "es6-iterator@~0.1.1", + "from": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", "dependencies": { "es6-symbol": { "version": "2.0.1", - "from": "es6-symbol@~2.0.1", + "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz" } } }, "es6-symbol": { "version": "0.1.1", - "from": "es6-symbol@0.1.x", + "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-0.1.1.tgz", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-0.1.1.tgz" } } }, "event-emitter": { "version": "0.3.3", - "from": "event-emitter@~0.3.1", + "from": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.3.tgz", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.3.tgz" }, "lru-queue": { "version": "0.1.0", - "from": "lru-queue@0.1", + "from": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz" }, "next-tick": { "version": "0.2.2", - "from": "next-tick@~0.2.2", + "from": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz" }, "timers-ext": { "version": "0.1.0", - "from": "timers-ext@0.1", + "from": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.0.tgz", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.0.tgz" } } @@ -9796,171 +9797,288 @@ } }, "protractor": { - "version": "1.7.0", - "from": "https://registry.npmjs.org/protractor/-/protractor-1.7.0.tgz", - "resolved": "https://registry.npmjs.org/protractor/-/protractor-1.7.0.tgz", + "version": "2.0.0", + "from": "protractor@2.0.0", "dependencies": { "request": { "version": "2.36.0", - "from": "https://registry.npmjs.org/request/-/request-2.36.0.tgz", + "from": "request@~2.36.0", "resolved": "https://registry.npmjs.org/request/-/request-2.36.0.tgz", "dependencies": { "qs": { "version": "0.6.6", - "from": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz", + "from": "qs@~0.6.0", "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz" }, "json-stringify-safe": { "version": "5.0.0", - "from": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz", + "from": "json-stringify-safe@~5.0.0", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" }, "mime": { "version": "1.2.11", - "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "from": "mime@~1.2.9", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "forever-agent": { "version": "0.5.2", - "from": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "from": "forever-agent@~0.5.0", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" }, "node-uuid": { - "version": "1.4.2", - "from": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz" + "version": "1.4.3", + "from": "node-uuid@~1.4.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" }, "tough-cookie": { "version": "0.12.1", - "from": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", + "from": "tough-cookie@>=0.12.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", "dependencies": { "punycode": { "version": "1.3.2", - "from": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "from": "punycode@>=0.2.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" } } }, "form-data": { "version": "0.1.4", - "from": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "from": "form-data@~0.1.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", "dependencies": { "combined-stream": { "version": "0.0.7", - "from": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "from": "combined-stream@~0.0.4", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", "dependencies": { "delayed-stream": { "version": "0.0.5", - "from": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "from": "delayed-stream@0.0.5", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" } } }, "async": { "version": "0.9.0", - "from": "https://registry.npmjs.org/async/-/async-0.9.0.tgz", + "from": "async@~0.9.0", "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" } } }, "tunnel-agent": { "version": "0.4.0", - "from": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz", + "from": "tunnel-agent@~0.4.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz" }, "http-signature": { "version": "0.10.1", - "from": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "from": "http-signature@~0.10.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", "dependencies": { "assert-plus": { "version": "0.1.5", - "from": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "from": "assert-plus@^0.1.5", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" }, "asn1": { "version": "0.1.11", - "from": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "from": "asn1@0.1.11", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" }, "ctype": { "version": "0.5.3", - "from": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "from": "ctype@0.5.3", "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" } } }, "oauth-sign": { "version": "0.3.0", - "from": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz", + "from": "oauth-sign@~0.3.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz" }, "hawk": { "version": "1.0.0", - "from": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz", + "from": "hawk@~1.0.0", "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz", "dependencies": { "hoek": { "version": "0.9.1", - "from": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "from": "hoek@0.9.x", "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" }, "boom": { "version": "0.4.2", - "from": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "from": "boom@0.4.x", "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" }, "cryptiles": { "version": "0.2.2", - "from": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "from": "cryptiles@0.2.x", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" }, "sntp": { "version": "0.2.4", - "from": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "from": "sntp@0.2.x", "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" } } }, "aws-sign2": { "version": "0.5.0", - "from": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "from": "aws-sign2@~0.5.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" } } }, "selenium-webdriver": { - "version": "2.44.0", - "from": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-2.44.0.tgz", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-2.44.0.tgz", + "version": "2.45.1", + "from": "selenium-webdriver@2.45.1", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-2.45.1.tgz", "dependencies": { + "rimraf": { + "version": "2.3.2", + "from": "rimraf@^2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.3.2.tgz", + "dependencies": { + "glob": { + "version": "4.5.3", + "from": "glob@^4.4.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "dependencies": { + "inflight": { + "version": "1.0.4", + "from": "inflight@^1.0.4", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.1", + "from": "wrappy@1", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" + } + } + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + }, + "minimatch": { + "version": "2.0.4", + "from": "minimatch@^2.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.4.tgz", + "dependencies": { + "brace-expansion": { + "version": "1.1.0", + "from": "brace-expansion@^1.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", + "dependencies": { + "balanced-match": { + "version": "0.2.0", + "from": "balanced-match@^0.2.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + } + } + } + } + }, + "once": { + "version": "1.3.1", + "from": "once@^1.3.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.1", + "from": "wrappy@1", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" + } + } + } + } + } + } + }, "tmp": { "version": "0.0.24", - "from": "https://registry.npmjs.org/tmp/-/tmp-0.0.24.tgz", + "from": "tmp@0.0.24", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.24.tgz" }, + "ws": { + "version": "0.7.1", + "from": "ws@^0.7.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-0.7.1.tgz", + "dependencies": { + "options": { + "version": "0.0.6", + "from": "options@>=0.0.5", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz" + }, + "ultron": { + "version": "1.0.1", + "from": "ultron@1.0.x", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.1.tgz" + }, + "bufferutil": { + "version": "1.0.1", + "from": "bufferutil@1.0.x", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-1.0.1.tgz", + "dependencies": { + "bindings": { + "version": "1.2.1", + "from": "bindings@1.2.x", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" + }, + "nan": { + "version": "1.6.2", + "from": "nan@1.6.x", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.6.2.tgz" + } + } + }, + "utf-8-validate": { + "version": "1.0.1", + "from": "utf-8-validate@1.0.x", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-1.0.1.tgz", + "dependencies": { + "bindings": { + "version": "1.2.1", + "from": "bindings@1.2.x", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" + }, + "nan": { + "version": "1.6.2", + "from": "nan@1.6.x", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.6.2.tgz" + } + } + } + } + }, "xml2js": { "version": "0.4.4", - "from": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.4.tgz", + "from": "xml2js@0.4.4", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.4.tgz", "dependencies": { "sax": { "version": "0.6.1", - "from": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz", + "from": "sax@0.6.x", "resolved": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz" }, "xmlbuilder": { - "version": "2.6.1", - "from": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.6.1.tgz", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.6.1.tgz", + "version": "2.6.2", + "from": "xmlbuilder@>=1.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.6.2.tgz", "dependencies": { "lodash": { - "version": "3.3.0", - "from": "https://registry.npmjs.org/lodash/-/lodash-3.3.0.tgz", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.3.0.tgz" + "version": "3.5.0", + "from": "lodash@~3.5.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.5.0.tgz" } } } @@ -9970,59 +10088,58 @@ }, "minijasminenode": { "version": "1.1.1", - "from": "https://registry.npmjs.org/minijasminenode/-/minijasminenode-1.1.1.tgz", + "from": "minijasminenode@1.1.1", "resolved": "https://registry.npmjs.org/minijasminenode/-/minijasminenode-1.1.1.tgz" }, "jasminewd": { "version": "1.1.0", - "from": "https://registry.npmjs.org/jasminewd/-/jasminewd-1.1.0.tgz", + "from": "jasminewd@1.1.0", "resolved": "https://registry.npmjs.org/jasminewd/-/jasminewd-1.1.0.tgz" }, "jasminewd2": { - "version": "0.0.2", - "from": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-0.0.2.tgz", - "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-0.0.2.tgz" + "version": "0.0.3", + "from": "jasminewd2@0.0.3" }, "jasmine": { "version": "2.1.1", - "from": "https://registry.npmjs.org/jasmine/-/jasmine-2.1.1.tgz", + "from": "jasmine@2.1.1", "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.1.1.tgz", "dependencies": { "jasmine-core": { "version": "2.1.3", - "from": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.1.3.tgz", + "from": "jasmine-core@~2.1.0", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.1.3.tgz" } } }, "saucelabs": { "version": "0.1.1", - "from": "https://registry.npmjs.org/saucelabs/-/saucelabs-0.1.1.tgz", + "from": "saucelabs@~0.1.0", "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-0.1.1.tgz" }, "glob": { "version": "3.2.11", - "from": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "from": "glob@~3.2", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@2", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "from": "minimatch@0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@~1.0.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -10031,49 +10148,59 @@ }, "adm-zip": { "version": "0.4.4", - "from": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.4.tgz", + "from": "adm-zip@0.4.4", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.4.tgz" }, "optimist": { "version": "0.6.1", - "from": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "from": "optimist@~0.6.0", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "dependencies": { "wordwrap": { "version": "0.0.2", - "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "from": "wordwrap@~0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" }, "minimist": { "version": "0.0.10", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "from": "minimist@~0.0.1", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } }, "q": { "version": "1.0.0", - "from": "https://registry.npmjs.org/q/-/q-1.0.0.tgz", + "from": "q@1.0.0", "resolved": "https://registry.npmjs.org/q/-/q-1.0.0.tgz" }, "source-map-support": { - "version": "0.2.9", - "from": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.9.tgz", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.9.tgz", + "version": "0.2.10", + "from": "source-map-support@~0.2.6", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.10.tgz", "dependencies": { "source-map": { "version": "0.1.32", - "from": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz", + "from": "source-map@0.1.32", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", + "from": "amdefine@>=0.0.4", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } } } + }, + "html-entities": { + "version": "1.1.2", + "from": "html-entities@~1.1.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.1.2.tgz" + }, + "accessibility-developer-tools": { + "version": "2.6.0", + "from": "accessibility-developer-tools@~2.6.0", + "resolved": "https://registry.npmjs.org/accessibility-developer-tools/-/accessibility-developer-tools-2.6.0.tgz" } } }, diff --git a/package.json b/package.json index 62541cd2e1a5..cb3b082bdd6d 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "marked": "~0.3.0", "node-html-encoder": "0.0.2", "promises-aplus-tests": "~2.1.0", - "protractor": "^1.6.0", + "protractor": "^2.0.0", "q": "~1.0.0", "q-io": "^1.10.9", "qq": "^0.3.5", From 7431ef78735098479013a652be1f9ade41f78a88 Mon Sep 17 00:00:00 2001 From: Julie Ralph Date: Thu, 19 Mar 2015 14:40:00 -0700 Subject: [PATCH 143/489] chore(ci): fix location of print logs from wait_for_browser_provider --- scripts/travis/wait_for_browser_provider.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/travis/wait_for_browser_provider.sh b/scripts/travis/wait_for_browser_provider.sh index 53d669b370eb..39332258c4b6 100755 --- a/scripts/travis/wait_for_browser_provider.sh +++ b/scripts/travis/wait_for_browser_provider.sh @@ -12,7 +12,7 @@ while [ ! -f $BROWSER_PROVIDER_READY_FILE ]; do # We must manually print logs here because travis will not run # after_script commands if the failure occurs before the script # phase. - ./print_logs.sh + ./scripts/travis/print_logs.sh exit 5 fi sleep .5 From 5e7524d624e3791f2f50475fa468f7f156441cc7 Mon Sep 17 00:00:00 2001 From: Wesley Cho Date: Thu, 19 Mar 2015 21:17:33 -0700 Subject: [PATCH 144/489] docs($httpBackend): change to more friendly language - Change s**t to more neutral word Closes #11380 Closes #11364 --- src/ng/httpBackend.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ng/httpBackend.js b/src/ng/httpBackend.js index 5ba78b749932..4eb872cd5f11 100644 --- a/src/ng/httpBackend.js +++ b/src/ng/httpBackend.js @@ -137,7 +137,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc }; function jsonpReq(url, callbackId, done) { - // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.: + // we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.: // - fetches local scripts via XHR and evals them // - adds and immediately removes script elements from the document var script = rawDocument.createElement('script'), callback = null; From cc6655961682200ef251251647e0eecf34f43d49 Mon Sep 17 00:00:00 2001 From: Vojta Jina Date: Wed, 28 Jan 2015 07:14:42 -0800 Subject: [PATCH 145/489] fix($rootScope): allow destroying a root scope When running (i.e. bootstrapping and killing) multiple apps on the same page, it makes sense to destroy the root scope. Closes #11241 Closes #10895 --- src/ng/rootScope.js | 7 +++---- test/ng/rootScopeSpec.js | 25 +++++++++++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/ng/rootScope.js b/src/ng/rootScope.js index a75f6e28938f..fc915b6ab037 100644 --- a/src/ng/rootScope.js +++ b/src/ng/rootScope.js @@ -871,13 +871,12 @@ function $RootScopeProvider() { * clean up DOM bindings before an element is removed from the DOM. */ $destroy: function() { - // we can't destroy the root scope or a scope that has been already destroyed + // We can't destroy a scope that has been already destroyed. if (this.$$destroyed) return; var parent = this.$parent; this.$broadcast('$destroy'); this.$$destroyed = true; - if (this === $rootScope) return; incrementWatchersCount(this, -this.$$watchersCount); for (var eventName in this.$$listenerCount) { @@ -886,8 +885,8 @@ function $RootScopeProvider() { // sever all the references to parent scopes (after this cleanup, the current scope should // not be retained by any of our references and should be eligible for garbage collection) - if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; - if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; + if (parent && parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; + if (parent && parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; diff --git a/test/ng/rootScopeSpec.js b/test/ng/rootScopeSpec.js index 75fb3232536c..7e145826538b 100644 --- a/test/ng/rootScopeSpec.js +++ b/test/ng/rootScopeSpec.js @@ -1021,16 +1021,33 @@ describe('Scope', function() { it('should broadcast $destroy on rootScope', inject(function($rootScope) { - var spy = spyOn(angular, 'noop'); - $rootScope.$on('$destroy', angular.noop); + var spy = jasmine.createSpy('$destroy handler'); + $rootScope.$on('$destroy', spy); $rootScope.$destroy(); - $rootScope.$digest(); - expect(log).toEqual('123'); expect(spy).toHaveBeenCalled(); expect($rootScope.$$destroyed).toBe(true); })); + it('should remove all listeners after $destroy of rootScope', inject(function($rootScope) { + var spy = jasmine.createSpy('$destroy handler'); + $rootScope.$on('dummy', spy); + $rootScope.$destroy(); + $rootScope.$broadcast('dummy'); + expect(spy).not.toHaveBeenCalled(); + })); + + + it('should remove all watchers after $destroy of rootScope', inject(function($rootScope) { + var spy = jasmine.createSpy('$watch spy'); + var digest = $rootScope.$digest; + $rootScope.$watch(spy); + $rootScope.$destroy(); + digest.call($rootScope); + expect(spy).not.toHaveBeenCalled(); + })); + + it('should remove first', inject(function($rootScope) { first.$destroy(); $rootScope.$digest(); From a95eee1245ad6d042a7854b8c78d35d0e09b998f Mon Sep 17 00:00:00 2001 From: RaphStein Date: Mon, 9 Mar 2015 18:06:08 +0100 Subject: [PATCH 146/489] docs(ngAria): change aria-live attribute value from polite to assertive For ngMessages directive ngAria generates aria-live with value assertive and not polite. Closes #11280 --- docs/content/guide/accessibility.ngdoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/guide/accessibility.ngdoc b/docs/content/guide/accessibility.ngdoc index 51a3cd34955f..2d5fdcfb6d26 100644 --- a/docs/content/guide/accessibility.ngdoc +++ b/docs/content/guide/accessibility.ngdoc @@ -235,7 +235,7 @@ Becomes: The new ngMessages module makes it easy to display form validation or other messages with priority sequencing and animation. To expose these visual messages to screen readers, -ngAria injects `aria-live="polite"`, causing them to be read aloud any time a message is shown, +ngAria injects `aria-live="assertive"`, causing them to be read aloud any time a message is shown, regardless of the user's focus location. ###Example @@ -249,7 +249,7 @@ regardless of the user's focus location. Becomes: ```html -
+
You did not enter a field
Your field is too long
From 40c41cd042000c77f01aa5c64f688f452840c181 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Sat, 21 Mar 2015 14:09:31 +0100 Subject: [PATCH 147/489] docs(guide/direcive): don't use shorthand in ddo All the other examples use the full syntax. Closes #11180 --- docs/content/guide/directive.ngdoc | 56 ++++++++++++++++-------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/docs/content/guide/directive.ngdoc b/docs/content/guide/directive.ngdoc index 13b4c5c0ecec..a3fad11a06d0 100644 --- a/docs/content/guide/directive.ngdoc +++ b/docs/content/guide/directive.ngdoc @@ -831,37 +831,39 @@ element? angular.module('dragModule', []) .directive('myDraggable', ['$document', function($document) { - return function(scope, element, attr) { - var startX = 0, startY = 0, x = 0, y = 0; - - element.css({ - position: 'relative', - border: '1px solid red', - backgroundColor: 'lightgrey', - cursor: 'pointer' - }); - - element.on('mousedown', function(event) { - // Prevent default dragging of selected content - event.preventDefault(); - startX = event.pageX - x; - startY = event.pageY - y; - $document.on('mousemove', mousemove); - $document.on('mouseup', mouseup); - }); + return { + link: function(scope, element, attr) { + var startX = 0, startY = 0, x = 0, y = 0; - function mousemove(event) { - y = event.pageY - startY; - x = event.pageX - startX; element.css({ - top: y + 'px', - left: x + 'px' + position: 'relative', + border: '1px solid red', + backgroundColor: 'lightgrey', + cursor: 'pointer' }); - } - function mouseup() { - $document.off('mousemove', mousemove); - $document.off('mouseup', mouseup); + element.on('mousedown', function(event) { + // Prevent default dragging of selected content + event.preventDefault(); + startX = event.pageX - x; + startY = event.pageY - y; + $document.on('mousemove', mousemove); + $document.on('mouseup', mouseup); + }); + + function mousemove(event) { + y = event.pageY - startY; + x = event.pageX - startX; + element.css({ + top: y + 'px', + left: x + 'px' + }); + } + + function mouseup() { + $document.off('mousemove', mousemove); + $document.off('mouseup', mouseup); + } } }; }]); From 8561dd9eb0b83a531e77440f179efbac38567d2b Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Sat, 21 Mar 2015 14:14:28 +0100 Subject: [PATCH 148/489] docs(guide/scope): fix grammar Closes #9829 --- docs/content/guide/scope.ngdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/guide/scope.ngdoc b/docs/content/guide/scope.ngdoc index 92999f82ba6d..5f843aea5312 100644 --- a/docs/content/guide/scope.ngdoc +++ b/docs/content/guide/scope.ngdoc @@ -245,7 +245,7 @@ of the `$watch` expressions and compares them with the previous value. This dirt asynchronously. This means that assignment such as `$scope.username="angular"` will not immediately cause a `$watch` to be notified, instead the `$watch` notification is delayed until the `$digest` phase. This delay is desirable, since it coalesces multiple model updates into one -`$watch` notification as well as it guarantees that during the `$watch` notification no other +`$watch` notification as well as guarantees that during the `$watch` notification no other `$watch`es are running. If a `$watch` changes the value of the model, it will force additional `$digest` cycle. From dde924cbbf8f65d2e94c87f91b04d74ccee12421 Mon Sep 17 00:00:00 2001 From: Yuvraj Patil Date: Fri, 20 Mar 2015 12:27:57 +0530 Subject: [PATCH 149/489] docs(guide/Unit Testing): update Jasmine's description Jasmine is a "behavior-driven development framework", not a "test-driven development framework" Closes #11383 --- docs/content/guide/unit-testing.ngdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/guide/unit-testing.ngdoc b/docs/content/guide/unit-testing.ngdoc index 6e3f2a205e94..8f811e3e87cd 100644 --- a/docs/content/guide/unit-testing.ngdoc +++ b/docs/content/guide/unit-testing.ngdoc @@ -62,7 +62,7 @@ are available on [the Karma website](http://karma-runner.github.io/0.12/intro/in ### Jasmine -[Jasmine](http://jasmine.github.io/1.3/introduction.html) is a test driven development framework for +[Jasmine](http://jasmine.github.io/1.3/introduction.html) is a behavior driven development framework for JavaScript that has become the most popular choice for testing Angular applications. Jasmine provides functions to help with structuring your tests and also making assertions. As your tests grow, keeping them well structured and documented is vital, and Jasmine helps achieve this. From f7d4663ec2e526682c6de88f6e7b1d360b20e947 Mon Sep 17 00:00:00 2001 From: wiseleo Date: Sat, 21 Mar 2015 23:36:39 -0700 Subject: [PATCH 150/489] docs(orderBy): replace operator = with === Fix documentation error on line 20 incorrectly mentioning an assignment operator in a comparison operation. Code on line 235 uses strict comparison operator. Closes #11392 Closes #11393 --- src/ng/filter/orderBy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ng/filter/orderBy.js b/src/ng/filter/orderBy.js index 41ef1c95fa07..cfab3bf575ce 100644 --- a/src/ng/filter/orderBy.js +++ b/src/ng/filter/orderBy.js @@ -17,7 +17,7 @@ * Can be one of: * * - `function`: Getter function. The result of this function will be sorted using the - * `<`, `=`, `>` operator. + * `<`, `===`, `>` operator. * - `string`: An Angular expression. The result of this expression is used to compare elements * (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by * 3 first characters of a property called `name`). The result of a constant expression From dba597183e21346d0bac5cf90ac211eb8d75973f Mon Sep 17 00:00:00 2001 From: Bradley Price Date: Sun, 22 Mar 2015 04:47:08 -0500 Subject: [PATCH 151/489] docs($http): remove trailing comma Remove trailing comma to keep the same flow with all other code examples on page. --- src/ng/http.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ng/http.js b/src/ng/http.js index 3a2e06c7474d..83f596286c49 100644 --- a/src/ng/http.js +++ b/src/ng/http.js @@ -377,7 +377,7 @@ function $HttpProvider() { * headers: { * 'Content-Type': undefined * }, - * data: { test: 'test' }, + * data: { test: 'test' } * } * * $http(req).success(function(){...}).error(function(){...}); From b6b39ee343bd46cbfb50c17fca898182314bd398 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Sun, 22 Mar 2015 13:53:51 +0100 Subject: [PATCH 152/489] docs($compile): clarify link fn's controller argument Also add "bindToController" to exampe directive definition object. Closes #10815 --- src/ng/compile.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index a071fcae56cc..7db7ad589b0e 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -76,6 +76,7 @@ * scope: false, * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... }, * controllerAs: 'stringIdentifier', + * bindToController: false, * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'], * compile: function compile(tElement, tAttrs, transclude) { * return { @@ -395,9 +396,15 @@ * * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared * between all directive linking functions. * - * * `controller` - a controller instance - A controller instance if at least one directive on the - * element defines a controller. The controller is shared among all the directives, which allows - * the directives to use the controllers as a communication channel. + * * `controller` - the directive's required controller instance(s) - Instances are shared + * among all directives, which allows the directives to use the controllers as a communication + * channel. The exact value depends on the directive's `require` property: + * * `string`: the controller instance + * * `array`: array of controller instances + * * no controller(s) required: `undefined` + * + * If a required controller cannot be found, and it is optional, the instance is `null`, + * otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown. * * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope. * This is the same as the `$transclude` From 6a3ac3f13cb82ca3be4df24809a1a2942480636a Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Mon, 23 Mar 2015 11:58:01 +0000 Subject: [PATCH 153/489] docs(filters): clarify filter name restrictions See #10122 --- docs/content/guide/filter.ngdoc | 6 ++++-- src/loader.js | 9 ++++++++- src/ng/filter.js | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/docs/content/guide/filter.ngdoc b/docs/content/guide/filter.ngdoc index 22eb4a5f163d..6830cfdea459 100644 --- a/docs/content/guide/filter.ngdoc +++ b/docs/content/guide/filter.ngdoc @@ -92,8 +92,10 @@ means that it should be stateless and idempotent. Angular relies on these proper the filter only when the inputs to the function change.
-**Note:** filter names must be valid angular expression identifiers, such as `uppercase` or `orderBy`. -Names with special characters, such as hyphens and dots, are not allowed. +**Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. +Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace +your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores +(`myapp_subsection_filterx`).
The following sample filter reverses a text string. In addition, it conditionally makes the diff --git a/src/loader.js b/src/loader.js index be4d1c2072c5..997a6c933d4b 100644 --- a/src/loader.js +++ b/src/loader.js @@ -243,10 +243,17 @@ function setupModuleLoader(window) { * @ngdoc method * @name angular.Module#filter * @module ng - * @param {string} name Filter name. + * @param {string} name Filter name - this must be a valid angular expression identifier * @param {Function} filterFactory Factory function for creating new instance of filter. * @description * See {@link ng.$filterProvider#register $filterProvider.register()}. + * + *
+ * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores + * (`myapp_subsection_filterx`). + *
*/ filter: invokeLater('$filterProvider', 'register'), diff --git a/src/ng/filter.js b/src/ng/filter.js index e32d1574f615..7c466152b9c6 100644 --- a/src/ng/filter.js +++ b/src/ng/filter.js @@ -20,6 +20,13 @@ * Dependency Injected. To achieve this a filter definition consists of a factory function which is * annotated with dependencies and is responsible for creating a filter function. * + *
+ * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores + * (`myapp_subsection_filterx`). + *
+ * * ```js * // Filter registration * function MyModule($provide, $filterProvider) { @@ -101,6 +108,13 @@ function $FilterProvider($provide) { * @name $filterProvider#register * @param {string|Object} name Name of the filter function, or an object map of filters where * the keys are the filter names and the values are the filter factories. + * + *
+ * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores + * (`myapp_subsection_filterx`). + *
* @returns {Object} Registered filter instance, or if a map of filters was provided then a map * of the registered filter instances. */ From 3b9e0fd40e41806dc6ded78d26658009a8210749 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Mon, 23 Mar 2015 12:09:39 +0000 Subject: [PATCH 154/489] docs(FAQ): add info about Anglar 1's versioning strategy See https://github.com/angular/angular.js/issues/10122#issuecomment-84139724 --- docs/content/misc/faq.ngdoc | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/docs/content/misc/faq.ngdoc b/docs/content/misc/faq.ngdoc index a6028333b9ab..6c7368d7d085 100644 --- a/docs/content/misc/faq.ngdoc +++ b/docs/content/misc/faq.ngdoc @@ -20,6 +20,42 @@ AngularJS is 100% JavaScript, 100% client-side and compatible with both desktop So it's definitely not a plugin or some other native browser extension. +### What is the AngularJS versioning strategy? + +In Angular 1 we do not allow intentional breaking changes to appear in versions where only the "patch" +number changes. For example between 1.3.12 and 1.3.13 there can be no breaking changes. We do allow +breaking changes happen between "minor" number changes. For example between 1.3.15 and 1.4.0 there +will be a number of breaking changes. We also allow breaking changes between beta releases of Angular. +For example between 1.4.0-beta.4 and 1.4.0-beta.5 there may be breaking changes. We try hard to minimize +these kinds of change only to those where there is a strong use case such as a strongly requested feature +improvement, a considerable simplification of the code or a measurable performance improvement. + +When adding new code to branches of Angular, have a very stringent commit policy: + +- Every commit must contain tests and documentation updates alongside the code changes and that all the +tests must pass; +- Commit messages must be written in a specific manner that allows us to parse them and extract the changes +for release notes. + +The Angular code base has a very large set of unit tests (over 4000) and end to end tests, which are pretty +comprehensive. This means that a breaking change will require one or more tests to be changed to allow the +tests to pass. So when a commit includes tests that are being removed or modified, this is a flag that the +code might include a breaking change. When reviewing the commit we can then decide whether there really is +a breaking change and if it is appropriate for the branch to which it is being merged. If so, then we +require that the commit message contains an appropriate breaking change message. + +Additionally, when a commit lands in our master repository it is synced to Google where we test it against +over 2000 applications using the test suites of these applications. This allows us to catch regressions +quickly before a release. We've had a pretty good experience with this setup. Only bugs that affect features +not used at Google or without sufficient test coverage, have a chance of making it through. + +Lastly, when we are making a release we generate updates to the changelog directly from the commits. This +generated update contains a highlighted section that contains all the breaking changes that have been +extracted fro the commits. We can quickly see in the new changelog exactly what commits contain breaking +changes and so can application developers when they are deciding whether to update to a new version of +Angular. + + ### Is AngularJS a templating system? At the highest level, Angular does look like just another templating system. But there is one From ae983541bcc8f95f1c3fb2eda3f20fa4fb091b64 Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Fri, 13 Feb 2015 21:15:40 -0800 Subject: [PATCH 155/489] perf(benchmark): add ngmodel benchmarks to largetable-bp Closes #11082 --- benchmarks/largetable-bp/main.html | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/benchmarks/largetable-bp/main.html b/benchmarks/largetable-bp/main.html index 471a4441dd9e..02270b5f2929 100644 --- a/benchmarks/largetable-bp/main.html +++ b/benchmarks/largetable-bp/main.html @@ -20,6 +20,8 @@
interpolation + fnInvocation:
ngBind + filter:
interpolation + filter:
+
ngModel (const name):
+
ngModel (interp name):
@@ -84,7 +86,21 @@

interpolation with filter

{{column.i | noop}}:{{column.j | noop}}|
+
+

ngModel (const name)

+
+ + +
+
+
+

ngModel (interp name)

+
+ + +
+
-
+
\ No newline at end of file From 5fb1ac1fab8623470b20e5e6f6f807dbe998eb8d Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 25 Mar 2015 14:02:49 +0000 Subject: [PATCH 156/489] docs(misc/FAQ): fix typo --- docs/content/misc/faq.ngdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/misc/faq.ngdoc b/docs/content/misc/faq.ngdoc index 6c7368d7d085..ec90fda84afd 100644 --- a/docs/content/misc/faq.ngdoc +++ b/docs/content/misc/faq.ngdoc @@ -51,7 +51,7 @@ not used at Google or without sufficient test coverage, have a chance of making Lastly, when we are making a release we generate updates to the changelog directly from the commits. This generated update contains a highlighted section that contains all the breaking changes that have been -extracted fro the commits. We can quickly see in the new changelog exactly what commits contain breaking +extracted from the commits. We can quickly see in the new changelog exactly what commits contain breaking changes and so can application developers when they are deciding whether to update to a new version of Angular. From 86f71cd7aad6370414c1e2afbe6c61f9c44aa4c2 Mon Sep 17 00:00:00 2001 From: Fred Sauer Date: Tue, 24 Mar 2015 14:48:39 -0700 Subject: [PATCH 157/489] docs($route): add param info for `$routeUpdate` event Closes #11419 --- src/ngRoute/route.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ngRoute/route.js b/src/ngRoute/route.js index 1826dac3d6df..1e46fbb33713 100644 --- a/src/ngRoute/route.js +++ b/src/ngRoute/route.js @@ -435,9 +435,11 @@ function $RouteProvider() { * @name $route#$routeUpdate * @eventType broadcast on root scope * @description - * * The `reloadOnSearch` property has been set to false, and we are reusing the same * instance of the Controller. + * + * @param {Object} angularEvent Synthetic event object + * @param {Route} current Current/previous route information. */ var forceReload = false, From ad285a460b8aaf07f9d7b0f7e3956d14b6a75bcb Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 25 Mar 2015 17:22:04 +0000 Subject: [PATCH 158/489] docs(ngMessageFormat): module name is actually ngMessageFormat --- src/ngMessageFormat/messageFormatService.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ngMessageFormat/messageFormatService.js b/src/ngMessageFormat/messageFormatService.js index 104218e1a5ab..2dca24c4bba7 100644 --- a/src/ngMessageFormat/messageFormatService.js +++ b/src/ngMessageFormat/messageFormatService.js @@ -10,7 +10,7 @@ /* global stringify: false */ /** - * @ngdoc module + * @ngdoc service * @name $$messageFormat * * @description @@ -57,7 +57,12 @@ var $$interpolateDecorator = ['$$messageFormat', '$delegate', function $$interpo return interpolate; }]; -// define ngMessageFormat module and register $$MessageFormat service + +/** + * @ngdoc module + * @name ngMessageFormat + * @description + */ var module = angular['module']('ngMessageFormat', ['ng']); module['provider']('$$messageFormat', $$MessageFormatProvider); module['config'](['$provide', function($provide) { From 534581370c808b7308fd800007e70438af510495 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 25 Mar 2015 17:26:45 +0000 Subject: [PATCH 159/489] style($$messageFormat) does not need to have a provider --- src/ngMessageFormat/messageFormatService.js | 48 ++++++++++----------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/ngMessageFormat/messageFormatService.js b/src/ngMessageFormat/messageFormatService.js index 2dca24c4bba7..21c8b2488a77 100644 --- a/src/ngMessageFormat/messageFormatService.js +++ b/src/ngMessageFormat/messageFormatService.js @@ -18,34 +18,32 @@ * For more information, see: * https://docs.google.com/a/google.com/document/d/1pbtW2yvtmFBikfRrJd8VAsabiFkKezmYZ_PbgdjQOVU/edit */ -function $$MessageFormatProvider() { - this['$get'] = ['$parse', '$locale', '$sce', '$exceptionHandler', function $get( +var $$MessageFormatFactory = ['$parse', '$locale', '$sce', '$exceptionHandler', function $$messageFormat( $parse, $locale, $sce, $exceptionHandler) { - function getStringifier(trustedContext, allOrNothing, text) { - return function stringifier(value) { - try { - value = trustedContext ? $sce['getTrusted'](trustedContext, value) : $sce['valueOf'](value); - return allOrNothing && (value === void 0) ? value : stringify(value); - } catch (err) { - $exceptionHandler($interpolateMinErr['interr'](text, err)); - } - }; - } + function getStringifier(trustedContext, allOrNothing, text) { + return function stringifier(value) { + try { + value = trustedContext ? $sce['getTrusted'](trustedContext, value) : $sce['valueOf'](value); + return allOrNothing && (value === void 0) ? value : stringify(value); + } catch (err) { + $exceptionHandler($interpolateMinErr['interr'](text, err)); + } + }; + } - function interpolate(text, mustHaveExpression, trustedContext, allOrNothing) { - var stringifier = getStringifier(trustedContext, allOrNothing, text); - var parser = new MessageFormatParser(text, 0, $parse, $locale['pluralCat'], stringifier, - mustHaveExpression, trustedContext, allOrNothing); - parser.run(parser.ruleInterpolate); - return parser.parsedFn; - } + function interpolate(text, mustHaveExpression, trustedContext, allOrNothing) { + var stringifier = getStringifier(trustedContext, allOrNothing, text); + var parser = new MessageFormatParser(text, 0, $parse, $locale['pluralCat'], stringifier, + mustHaveExpression, trustedContext, allOrNothing); + parser.run(parser.ruleInterpolate); + return parser.parsedFn; + } - return { - 'interpolate': interpolate - }; - }]; -} + return { + 'interpolate': interpolate + }; +}]; var $$interpolateDecorator = ['$$messageFormat', '$delegate', function $$interpolateDecorator($$messageFormat, $interpolate) { if ($interpolate['startSymbol']() != "{{" || $interpolate['endSymbol']() != "}}") { @@ -64,7 +62,7 @@ var $$interpolateDecorator = ['$$messageFormat', '$delegate', function $$interpo * @description */ var module = angular['module']('ngMessageFormat', ['ng']); -module['provider']('$$messageFormat', $$MessageFormatProvider); +module['factory']('$$messageFormat', $$MessageFormatFactory); module['config'](['$provide', function($provide) { $provide['decorator']('$interpolate', $$interpolateDecorator); }]); From d215f08b689549ec4fcd176c3ab4de27d75cef9b Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Mon, 23 Mar 2015 23:07:04 +0100 Subject: [PATCH 160/489] fix(select): don't call $render twice if $viewValue ref changes Credits to @tepez for the fix Closes #11329 Closes #11412 --- src/ng/directive/select.js | 5 +-- test/ng/directive/selectSpec.js | 54 +++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/ng/directive/select.js b/src/ng/directive/select.js index 66e48bc0ef9d..b0b69aca1f83 100644 --- a/src/ng/directive/select.js +++ b/src/ng/directive/select.js @@ -141,7 +141,6 @@ var SelectController = * */ var selectDirective = function() { - var lastView; return { restrict: 'E', @@ -200,11 +199,13 @@ var selectDirective = function() { // we have to do it on each watch since ngModel watches reference, but // we need to work of an array, so we need to see if anything was inserted/removed + var lastView, lastViewRef = NaN; scope.$watch(function selectMultipleWatch() { - if (!equals(lastView, ngModelCtrl.$viewValue)) { + if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastView, ngModelCtrl.$viewValue)) { lastView = shallowCopy(ngModelCtrl.$viewValue); ngModelCtrl.$render(); } + lastViewRef = ngModelCtrl.$viewValue; }); // If we are a multiple select then value is now a collection diff --git a/test/ng/directive/selectSpec.js b/test/ng/directive/selectSpec.js index af6262a56166..5be377aa54ee 100644 --- a/test/ng/directive/selectSpec.js +++ b/test/ng/directive/selectSpec.js @@ -841,6 +841,60 @@ describe('select', function() { expect(element).toBeDirty(); }); + + describe('calls to $render', function() { + + var ngModelCtrl; + + beforeEach(function() { + compile( + ''); + + ngModelCtrl = element.controller('ngModel'); + spyOn(ngModelCtrl, '$render').andCallThrough(); + }); + + + it('should call $render once when the reference to the viewValue changes', function() { + scope.$apply(function() { + scope.selection = ['A']; + }); + expect(ngModelCtrl.$render.calls.length).toBe(1); + + scope.$apply(function() { + scope.selection = ['A', 'B']; + }); + expect(ngModelCtrl.$render.calls.length).toBe(2); + + scope.$apply(function() { + scope.selection = []; + }); + expect(ngModelCtrl.$render.calls.length).toBe(3); + }); + + + it('should call $render once when the viewValue deep-changes', function() { + scope.$apply(function() { + scope.selection = ['A']; + }); + expect(ngModelCtrl.$render.calls.length).toBe(1); + + scope.$apply(function() { + scope.selection.push('B'); + }); + expect(ngModelCtrl.$render.calls.length).toBe(2); + + scope.$apply(function() { + scope.selection.length = 0; + }); + expect(ngModelCtrl.$render.calls.length).toBe(3); + }); + + }); + }); From 65d71bae1afc3f7b83cdc2813018de18d45913b7 Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Fri, 27 Mar 2015 12:24:48 +0200 Subject: [PATCH 161/489] refactor($compile): remove unused `return` statement As discussed in https://github.com/angular/angular.js/commit/89447b3f2b4c6db62c24473a81fedc3b04242b85#commitcomment-10280666. --- src/ng/compile.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index 7db7ad589b0e..1268cbc59a9a 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -802,7 +802,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (!letter || letter !== lowercase(letter)) { throw $compileMinErr('baddir', "Directive name '{0}' is invalid. The first character must be a lowercase letter", name); } - return name; } /** From e41c5249f49562a44e648227bcc2e33d50aa67aa Mon Sep 17 00:00:00 2001 From: Brent Dearth Date: Fri, 27 Mar 2015 13:55:48 -0400 Subject: [PATCH 162/489] perf(ngOptions): only perform deep equality check on ngModel if using track by Closes #11448 Closes #11447 --- src/ng/directive/ngOptions.js | 16 +++++++---- src/ng/directive/select.js | 5 ++-- test/ng/directive/ngOptionsSpec.js | 44 ++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/src/ng/directive/ngOptions.js b/src/ng/directive/ngOptions.js index 476da491d755..a612613698cd 100644 --- a/src/ng/directive/ngOptions.js +++ b/src/ng/directive/ngOptions.js @@ -32,8 +32,9 @@ var ngOptionsMinErr = minErr('ngOptions'); * option. See example below for demonstration. * *
- * **Note:** `ngModel` compares by reference, not value. This is important when binding to an - * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/). + * **Note:** By default, `ngModel` compares by reference, not value. This is important when binding to an + * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/). When using `track by` + * in an `ngOptions` expression, however, deep equality checks will be performed. *
* * ## `select` **`as`** @@ -275,6 +276,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { } return { + trackBy: trackBy, getWatchables: $parse(valuesFn, function(values) { // Create a collection of things that we would like to watch (watchedArray) // so that they can all be watched using a single $watchCollection @@ -500,8 +502,9 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { // We also need to watch to see if the internals of the model changes, since // ngModel only watches for object identity change - scope.$watch(attr.ngModel, function() { ngModelCtrl.$render(); }, true); - + if (ngOptions.trackBy) { + scope.$watch(attr.ngModel, function() { ngModelCtrl.$render(); }, true); + } // ------------------------------------------------------------------ // @@ -643,10 +646,13 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { // Check to see if the value has changed due to the update to the options if (!ngModelCtrl.$isEmpty(previousValue)) { var nextValue = selectCtrl.readValue(); - if (!equals(previousValue, nextValue)) { + if (ngOptions.trackBy && !equals(previousValue, nextValue) || + previousValue !== nextValue) { ngModelCtrl.$setViewValue(nextValue); + ngModelCtrl.$render(); } } + } } diff --git a/src/ng/directive/select.js b/src/ng/directive/select.js index b0b69aca1f83..6533fe8906c5 100644 --- a/src/ng/directive/select.js +++ b/src/ng/directive/select.js @@ -135,8 +135,9 @@ var SelectController = * option. See example below for demonstration. * *
- * **Note:** `ngModel` compares by reference, not value. This is important when binding to an - * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/). + * **Note:** By default, `ngModel` compares by reference, not value. This is important when binding to an + * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/). When using `track by` + * in an `ngOptions` expression, however, deep equality checks will be performed. *
* */ diff --git a/test/ng/directive/ngOptionsSpec.js b/test/ng/directive/ngOptionsSpec.js index ceb3e312f494..97b58dee9c20 100644 --- a/test/ng/directive/ngOptionsSpec.js +++ b/test/ng/directive/ngOptionsSpec.js @@ -1041,6 +1041,50 @@ describe('ngOptions', function() { }); }).not.toThrow(); }); + + it('should setup equality watches on ngModel changes if using trackBy', function() { + + createSelect({ + 'ng-model': 'selected', + 'ng-options': 'item for item in arr track by item.id' + }); + + scope.$apply(function() { + scope.selected = scope.arr[0]; + }); + + spyOn(element.controller('ngModel'), '$render'); + + scope.$apply(function() { + scope.selected.label = 'changed'; + }); + + // update render due to equality watch + expect(element.controller('ngModel').$render).toHaveBeenCalled(); + + }); + + it('should not setup equality watches on ngModel changes if not using trackBy', function() { + + createSelect({ + 'ng-model': 'selected', + 'ng-options': 'item for item in arr' + }); + + scope.$apply(function() { + scope.selected = scope.arr[0]; + }); + + spyOn(element.controller('ngModel'), '$render'); + + scope.$apply(function() { + scope.selected.label = 'changed'; + }); + + // no render update as no equality watch + expect(element.controller('ngModel').$render).not.toHaveBeenCalled(); + }); + }); From bb8fd7db22aea93a043a1b52e019890fbf839959 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Mon, 23 Mar 2015 21:35:50 +0100 Subject: [PATCH 163/489] test(ngStyle): ensure lazy one-time binding is supported Closes #11405 --- test/ng/directive/ngStyleSpec.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/ng/directive/ngStyleSpec.js b/test/ng/directive/ngStyleSpec.js index 89056f539326..b531296d7c0f 100644 --- a/test/ng/directive/ngStyleSpec.js +++ b/test/ng/directive/ngStyleSpec.js @@ -23,6 +23,15 @@ describe('ngStyle', function() { })); + it('should support lazy one-time binding for object literals', inject(function($rootScope, $compile) { + element = $compile('
')($rootScope); + $rootScope.$digest(); + expect(element.css('height')).toBeFalsy(); + $rootScope.$apply('heightStr = "40px"'); + expect(element.css('height')).toBe('40px'); + })); + + describe('preserving styles set before and after compilation', function() { var scope, preCompStyle, preCompVal, postCompStyle, postCompVal, element; From be091ae8a4541fece861b7397d6de6d0c4fb48ca Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Mon, 23 Mar 2015 21:33:26 +0100 Subject: [PATCH 164/489] Revert "perf(ngStyleDirective): use $watchCollection" This reverts commit 4c8d8ad5083d9dd17c0b8480339d5f95943f1b71, because it broke lazy one-time binding for object literals (introduced in c024f28217cf8eedd695dd4b933ecf2ba4243c15) Fixes #11403 --- src/ng/directive/ngStyle.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ng/directive/ngStyle.js b/src/ng/directive/ngStyle.js index 72c7ce0e544a..16da9bec496b 100644 --- a/src/ng/directive/ngStyle.js +++ b/src/ng/directive/ngStyle.js @@ -47,10 +47,10 @@ */ var ngStyleDirective = ngDirective(function(scope, element, attr) { - scope.$watchCollection(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) { + scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) { if (oldStyles && (newStyles !== oldStyles)) { forEach(oldStyles, function(val, style) { element.css(style, '');}); } if (newStyles) element.css(newStyles); - }); + }, true); }); From 5d5a3b377db25aa2eb0cdebcdfd12172016e2dbf Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Tue, 31 Mar 2015 16:09:14 +0100 Subject: [PATCH 165/489] test(ngStyle): should cope with both `''` and `'0px'` for initial height --- test/ng/directive/ngStyleSpec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ng/directive/ngStyleSpec.js b/test/ng/directive/ngStyleSpec.js index b531296d7c0f..a5dbe83ffdef 100644 --- a/test/ng/directive/ngStyleSpec.js +++ b/test/ng/directive/ngStyleSpec.js @@ -23,10 +23,10 @@ describe('ngStyle', function() { })); - it('should support lazy one-time binding for object literals', inject(function($rootScope, $compile) { + it('should support lazy one-time binding for object literals', inject(function($rootScope, $compile, $log) { element = $compile('
')($rootScope); $rootScope.$digest(); - expect(element.css('height')).toBeFalsy(); + expect(parseInt(element.css('height') + 0)).toEqual(0); // height could be '' or '0px' $rootScope.$apply('heightStr = "40px"'); expect(element.css('height')).toBe('40px'); })); From c4c9e7d0deffed1c08ec2368c6dcf28a6f796aa5 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Tue, 31 Mar 2015 16:33:47 +0100 Subject: [PATCH 166/489] style(ngStyle): remove unused $log param --- test/ng/directive/ngStyleSpec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ng/directive/ngStyleSpec.js b/test/ng/directive/ngStyleSpec.js index a5dbe83ffdef..4d1ef2069bea 100644 --- a/test/ng/directive/ngStyleSpec.js +++ b/test/ng/directive/ngStyleSpec.js @@ -23,7 +23,7 @@ describe('ngStyle', function() { })); - it('should support lazy one-time binding for object literals', inject(function($rootScope, $compile, $log) { + it('should support lazy one-time binding for object literals', inject(function($rootScope, $compile) { element = $compile('
')($rootScope); $rootScope.$digest(); expect(parseInt(element.css('height') + 0)).toEqual(0); // height could be '' or '0px' From 34a5bc26e20acf943bc5962eb15eb5e58cf8b2ee Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Fri, 27 Mar 2015 12:44:56 +0200 Subject: [PATCH 167/489] style(filterFilter): fix indentation and remove newline for consistency --- test/ng/filter/filterSpec.js | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/test/ng/filter/filterSpec.js b/test/ng/filter/filterSpec.js index 217ad25c5f7f..8537bc72b3a1 100644 --- a/test/ng/filter/filterSpec.js +++ b/test/ng/filter/filterSpec.js @@ -438,31 +438,31 @@ describe('Filter: filter', function() { it('should not throw an error if property is null when comparing object', function() { - var items = [ - { office:1, people: {name:'john'}}, - { office:2, people: {name:'jane'}}, - { office:3, people: null} - ]; - var f = { }; - expect(filter(items, f).length).toBe(3); - - f = { people:null }; - expect(filter(items, f).length).toBe(1); + var items = [ + { office:1, people: {name:'john'}}, + { office:2, people: {name:'jane'}}, + { office:3, people: null} + ]; + var f = { }; + expect(filter(items, f).length).toBe(3); - f = { people: {}}; - expect(filter(items, f).length).toBe(2); + f = { people:null }; + expect(filter(items, f).length).toBe(1); - f = { people:{ name: '' }}; - expect(filter(items, f).length).toBe(2); + f = { people: {}}; + expect(filter(items, f).length).toBe(2); - f = { people:{ name:'john' }}; - expect(filter(items, f).length).toBe(1); + f = { people:{ name: '' }}; + expect(filter(items, f).length).toBe(2); - f = { people:{ name:'j' }}; - expect(filter(items, f).length).toBe(2); + f = { people:{ name:'john' }}; + expect(filter(items, f).length).toBe(1); + f = { people:{ name:'j' }}; + expect(filter(items, f).length).toBe(2); }); + describe('should support comparator', function() { it('not consider objects without a custom `toString` in non-strict comparison', function() { From 9421bef17f2450ea805d6fc39898135e7039fac2 Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Fri, 27 Mar 2015 16:48:06 +0200 Subject: [PATCH 168/489] fix(filterFilter): fix matching against `null`/`undefined` Included fixes: * Do not convert `null`/`undefined` to strings for substring matching in non-strict comparison mode. Prevents `null`/`undefined` from being matched against e.g. 'u'. * Let `null` (as a top-level filter expression) match "deeply" (as do booleans, numbers and strings). E.g. let `filterFilter(arr, null)` match an item like `{someProp: null}`. Closes #11432 Closes #11445 --- src/ng/filter/filter.js | 12 ++++++++- test/ng/filter/filterSpec.js | 51 ++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/ng/filter/filter.js b/src/ng/filter/filter.js index 3b6b444d3375..d658de900e65 100644 --- a/src/ng/filter/filter.js +++ b/src/ng/filter/filter.js @@ -135,14 +135,16 @@ function filterFilter() { } } + var expressionType = (expression !== null) ? typeof expression : 'null'; var predicateFn; var matchAgainstAnyProp; - switch (typeof expression) { + switch (expressionType) { case 'function': predicateFn = expression; break; case 'boolean': + case 'null': case 'number': case 'string': matchAgainstAnyProp = true; @@ -172,6 +174,14 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) { comparator = equals; } else if (!isFunction(comparator)) { comparator = function(actual, expected) { + if (isUndefined(actual)) { + // No substring matching against `undefined` + return false; + } + if ((actual === null) || (expected === null)) { + // No substring matching against `null`; only match against `null` + return actual === expected; + } if (isObject(expected) || (isObject(actual) && !hasCustomToString(actual))) { // Should not compare primitives against objects, unless they have custom `toString` method return false; diff --git a/test/ng/filter/filterSpec.js b/test/ng/filter/filterSpec.js index 8537bc72b3a1..fb71ef054ab3 100644 --- a/test/ng/filter/filterSpec.js +++ b/test/ng/filter/filterSpec.js @@ -463,8 +463,59 @@ describe('Filter: filter', function() { }); + it('should match `null` against `null` only', function() { + var items = [ + {value: null}, + {value: undefined}, + {value: true}, + {value: false}, + {value: NaN}, + {value: 42}, + {value: 'null'}, + {value: 'test'}, + {value: {}}, + {value: new Date()} + ]; + var flt; + + flt = null; + expect(filter(items, flt).length).toBe(1); + expect(filter(items, flt)[0]).toBe(items[0]); + + flt = {value: null}; + expect(filter(items, flt).length).toBe(1); + expect(filter(items, flt)[0]).toBe(items[0]); + + flt = {value: undefined}; + expect(filter(items, flt).length).toBe(items.length); + + flt = {value: NaN}; + expect(includes(filter(items, flt), items[0])).toBeFalsy(); + + flt = {value: false}; + expect(includes(filter(items, flt), items[0])).toBeFalsy(); + + flt = ''; + expect(includes(filter(items, flt), items[0])).toBeFalsy(); + + flt = {value: 'null'}; + expect(includes(filter(items, flt), items[0])).toBeFalsy(); + }); + + describe('should support comparator', function() { + it('not convert `null` or `undefined` to string in non-strict comparison', function() { + var items = [ + {value: null}, + {value: undefined} + ]; + var flt = {value: 'u'}; + + expect(filter(items, flt).length).toBe(0); + }); + + it('not consider objects without a custom `toString` in non-strict comparison', function() { var items = [{test: {}}]; var expr = '[object'; From 9c4e741db4a85aa6d011e3f4a03135a2af6df9c3 Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Fri, 27 Mar 2015 16:59:22 +0200 Subject: [PATCH 169/489] refactor(filterFilter): introduce helper function for "DRYness" --- src/ng/filter/filter.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ng/filter/filter.js b/src/ng/filter/filter.js index d658de900e65..6e29e2cf5a87 100644 --- a/src/ng/filter/filter.js +++ b/src/ng/filter/filter.js @@ -135,7 +135,7 @@ function filterFilter() { } } - var expressionType = (expression !== null) ? typeof expression : 'null'; + var expressionType = getTypeForFilter(expression); var predicateFn; var matchAgainstAnyProp; @@ -204,8 +204,8 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) { } function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) { - var actualType = (actual !== null) ? typeof actual : 'null'; - var expectedType = (expected !== null) ? typeof expected : 'null'; + var actualType = getTypeForFilter(actual); + var expectedType = getTypeForFilter(expected); if ((expectedType === 'string') && (expected.charAt(0) === '!')) { return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp); @@ -251,3 +251,8 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatc return comparator(actual, expected); } } + +// Used for easily differentiating between `null` and actual `object` +function getTypeForFilter(val) { + return (val === null) ? 'null' : typeof val; +} From db12bb6a58f5505fe21a1740ff7d898905bd8f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Mon, 30 Mar 2015 21:21:09 -0700 Subject: [PATCH 170/489] fix(ngAnimate): ensure that minified repaint code isn't removed Closes #9936 --- src/ngAnimate/animate.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ngAnimate/animate.js b/src/ngAnimate/animate.js index 71ed2ec4d0d5..b87ed335cb2b 100644 --- a/src/ngAnimate/animate.js +++ b/src/ngAnimate/animate.js @@ -432,9 +432,11 @@ angular.module('ngAnimate', ['ng']) //so that all the animated elements within the animation frame //will be properly updated and drawn on screen. This is //required to perform multi-class CSS based animations with - //Firefox. DO NOT REMOVE THIS LINE. - var a = bod.offsetWidth + 1; - fn(); + //Firefox. DO NOT REMOVE THIS LINE. DO NOT OPTIMIZE THIS LINE. + //THE MINIFIER WILL REMOVE IT OTHERWISE WHICH WILL RESULT IN AN + //UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND WILL + //TAKE YEARS AWAY FROM YOUR LIFE! + fn(bod.offsetWidth); }); }; }]) From 249d55019a59ba592471b2d43efb33b23352577d Mon Sep 17 00:00:00 2001 From: Lucas Galfaso Date: Wed, 1 Apr 2015 14:02:57 +0200 Subject: [PATCH 171/489] fix($parse): fix parse errors on older Android WebViews which choke with reserved keywords Closes #11455 --- src/ng/parse.js | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/ng/parse.js b/src/ng/parse.js index f3386c74e80b..7084acb1d46a 100644 --- a/src/ng/parse.js +++ b/src/ng/parse.js @@ -784,7 +784,7 @@ ASTCompiler.prototype = { self.state.computing = fnKey; var intoId = self.nextId(); self.recurse(watch, intoId); - self.return(intoId); + self.return_(intoId); self.state.inputs.push(fnKey); watch.watchId = key; }); @@ -871,7 +871,7 @@ ASTCompiler.prototype = { recursionFn = recursionFn || noop; if (!skipWatchIdCheck && isDefined(ast.watchId)) { intoId = intoId || this.nextId(); - this.if('i', + this.if_('i', this.lazyAssign(intoId, this.computedMember('i', ast.watchId)), this.lazyRecurse(ast, intoId, nameId, recursionFn, create, true) ); @@ -884,7 +884,7 @@ ASTCompiler.prototype = { if (pos !== ast.body.length - 1) { self.current().body.push(right, ';'); } else { - self.return(right); + self.return_(right); } }); break; @@ -915,13 +915,13 @@ ASTCompiler.prototype = { case AST.LogicalExpression: intoId = intoId || this.nextId(); self.recurse(ast.left, intoId); - self.if(ast.operator === '&&' ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId)); + self.if_(ast.operator === '&&' ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId)); recursionFn(intoId); break; case AST.ConditionalExpression: intoId = intoId || this.nextId(); self.recurse(ast.test, intoId); - self.if(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId)); + self.if_(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId)); recursionFn(intoId); break; case AST.Identifier: @@ -932,11 +932,11 @@ ASTCompiler.prototype = { nameId.name = ast.name; } ensureSafeMemberName(ast.name); - self.if(self.stage === 'inputs' || self.not(self.getHasOwnProperty('l', ast.name)), + self.if_(self.stage === 'inputs' || self.not(self.getHasOwnProperty('l', ast.name)), function() { - self.if(self.stage === 'inputs' || 's', function() { + self.if_(self.stage === 'inputs' || 's', function() { if (create && create !== 1) { - self.if( + self.if_( self.not(self.nonComputedMember('s', ast.name)), self.lazyAssign(self.nonComputedMember('s', ast.name), '{}')); } @@ -953,13 +953,13 @@ ASTCompiler.prototype = { left = nameId && (nameId.context = this.nextId()) || this.nextId(); intoId = intoId || this.nextId(); self.recurse(ast.object, left, undefined, function() { - self.if(self.notNull(left), function() { + self.if_(self.notNull(left), function() { if (ast.computed) { right = self.nextId(); self.recurse(ast.property, right); self.addEnsureSafeMemberName(right); if (create && create !== 1) { - self.if(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}')); + self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}')); } expression = self.ensureSafeObject(self.computedMember(left, right)); self.assign(intoId, expression); @@ -970,7 +970,7 @@ ASTCompiler.prototype = { } else { ensureSafeMemberName(ast.property.name); if (create && create !== 1) { - self.if(self.not(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), '{}')); + self.if_(self.not(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), '{}')); } expression = self.nonComputedMember(left, ast.property.name); if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.property.name)) { @@ -1004,7 +1004,7 @@ ASTCompiler.prototype = { left = {}; args = []; self.recurse(ast.callee, right, left, function() { - self.if(self.notNull(right), function() { + self.if_(self.notNull(right), function() { self.addEnsureSafeFunction(right); forEach(ast.arguments, function(expr) { self.recurse(expr, self.nextId(), undefined, function(argument) { @@ -1033,7 +1033,7 @@ ASTCompiler.prototype = { throw $parseMinErr('lval', 'Trying to assing a value to a non l-value'); } this.recurse(ast.left, undefined, left, function() { - self.if(self.notNull(left.context), function() { + self.if_(self.notNull(left.context), function() { self.recurse(ast.right, right); self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); expression = self.member(left.context, left.name, left.computed) + ast.operator + right; @@ -1108,11 +1108,11 @@ ASTCompiler.prototype = { return 'plus(' + left + ',' + right + ')'; }, - 'return': function(id) { + return_: function(id) { this.current().body.push('return ', id, ';'); }, - 'if': function(test, alternate, consequent) { + if_: function(test, alternate, consequent) { if (test === true) { alternate(); } else { From e6220e6855d6a992e064ace38b62c7e370c001bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82=C4=99biowski?= Date: Wed, 1 Apr 2015 18:06:25 +0200 Subject: [PATCH 172/489] feat(travis): run unit tests on iOS 8 Refs #11471 Closes #11479 --- karma-shared.conf.js | 12 ++++++++++++ scripts/travis/build.sh | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/karma-shared.conf.js b/karma-shared.conf.js index 1f0fe672284e..3885f0b98c5e 100644 --- a/karma-shared.conf.js +++ b/karma-shared.conf.js @@ -66,6 +66,12 @@ module.exports = function(config, specificOptions) { platform: 'Windows 8.1', version: '11' }, + 'SL_iOS': { + base: "SauceLabs", + browserName: "iphone", + platform: "OS X 10.10", + version: "8.1" + }, 'BS_Chrome': { base: 'BrowserStack', @@ -105,6 +111,12 @@ module.exports = function(config, specificOptions) { browser_version: '11.0', os: 'Windows', os_version: '8.1' + }, + 'BS_iOS': { + base: 'BrowserStack', + device: 'iPhone 6', + os: 'ios', + os_version: '8.0' } } }); diff --git a/scripts/travis/build.sh b/scripts/travis/build.sh index baeda7baf015..9e4f4fcd180a 100755 --- a/scripts/travis/build.sh +++ b/scripts/travis/build.sh @@ -7,9 +7,9 @@ export SAUCE_ACCESS_KEY=`echo $SAUCE_ACCESS_KEY | rev` if [ $JOB = "unit" ]; then if [ "$BROWSER_PROVIDER" == "browserstack" ]; then - BROWSERS="BS_Chrome,BS_Safari,BS_Firefox,BS_IE_9,BS_IE_10,BS_IE_11" + BROWSERS="BS_Chrome,BS_Safari,BS_Firefox,BS_IE_9,BS_IE_10,BS_IE_11,BS_iOS" else - BROWSERS="SL_Chrome,SL_Safari,SL_Firefox,SL_IE_9,SL_IE_10,SL_IE_11" + BROWSERS="SL_Chrome,SL_Safari,SL_Firefox,SL_IE_9,SL_IE_10,SL_IE_11,SL_iOS" fi grunt test:promises-aplus From d5107ecbff923ae96674c04d89ef7b828abfbfd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82=C4=99biowski?= Date: Tue, 31 Mar 2015 15:59:19 +0200 Subject: [PATCH 173/489] fix(ngTouch): register touches properly when jQuery is used If jQuery was used with Angular the touch logic was looking for touches under the original event object. However, jQuery wraps all events, keeping the original one under the originalEvent property and copies/normalizes some of event properties. Not all properties are copied, e.g. touches which caused them to not be recognized properly. Thanks to @mcmar & @pomerantsev for original patch ideas. Fixes #4001 Closes #8584 Closes #10797 Closes #11488 --- src/ngScenario/browserTrigger.js | 35 ++++++++++++++++++++++ src/ngTouch/directive/ngClick.js | 15 ++++++---- src/ngTouch/swipe.js | 8 ++--- test/ngTouch/directive/ngClickSpec.js | 43 +++++++++++++++++++++++++-- test/ngTouch/swipeSpec.js | 4 +-- 5 files changed, 91 insertions(+), 14 deletions(-) diff --git a/src/ngScenario/browserTrigger.js b/src/ngScenario/browserTrigger.js index 35aa54aad93e..bcbdb27acc29 100644 --- a/src/ngScenario/browserTrigger.js +++ b/src/ngScenario/browserTrigger.js @@ -77,6 +77,8 @@ evnt.initAnimationEvent(eventType, null, null, null, eventData.elapsedTime || 0); } } + } else if (/touch/.test(eventType) && supportsTouchEvents()) { + evnt = createTouchEvent(element, eventType, x, y); } else { evnt = document.createEvent('MouseEvents'); x = x || 0; @@ -112,4 +114,37 @@ return finalProcessDefault; }; + + function supportsTouchEvents() { + if ('_cached' in supportsTouchEvents) { + return supportsTouchEvents._cached; + } + if (!document.createTouch || !document.createTouchList) { + supportsTouchEvents._cached = false; + return false; + } + try { + document.createEvent('TouchEvent'); + } catch (e) { + supportsTouchEvents._cached = false; + return false; + } + supportsTouchEvents._cached = true; + return true; + } + + function createTouchEvent(element, eventType, x, y) { + var evnt = document.createEvent('TouchEvent'); + x = x || 0; + y = y || 0; + + var touch = document.createTouch(window, element, Date.now(), x, y, x, y); + var touches = document.createTouchList(touch); + var targetTouches = document.createTouchList(touch); + var changedTouches = document.createTouchList(touch); + + evnt.initTouchEvent(eventType, true, true, window, null, 0, 0, 0, 0, false, false, false, false, + touches, targetTouches, changedTouches, 1, 0); + return evnt; + } }()); diff --git a/src/ngTouch/directive/ngClick.js b/src/ngTouch/directive/ngClick.js index 90274aba7322..4d48f8e86a28 100644 --- a/src/ngTouch/directive/ngClick.js +++ b/src/ngTouch/directive/ngClick.js @@ -221,8 +221,10 @@ ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement', startTime = Date.now(); - var touches = event.touches && event.touches.length ? event.touches : [event]; - var e = touches[0].originalEvent || touches[0]; + // Use jQuery originalEvent + var originalEvent = event.originalEvent || event; + var touches = originalEvent.touches && originalEvent.touches.length ? originalEvent.touches : [originalEvent]; + var e = touches[0]; touchStartX = e.clientX; touchStartY = e.clientY; }); @@ -238,9 +240,12 @@ ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement', element.on('touchend', function(event) { var diff = Date.now() - startTime; - var touches = (event.changedTouches && event.changedTouches.length) ? event.changedTouches : - ((event.touches && event.touches.length) ? event.touches : [event]); - var e = touches[0].originalEvent || touches[0]; + // Use jQuery originalEvent + var originalEvent = event.originalEvent || event; + var touches = (originalEvent.changedTouches && originalEvent.changedTouches.length) ? + originalEvent.changedTouches : + ((originalEvent.touches && originalEvent.touches.length) ? originalEvent.touches : [originalEvent]); + var e = touches[0]; var x = e.clientX; var y = e.clientY; var dist = Math.sqrt(Math.pow(x - touchStartX, 2) + Math.pow(y - touchStartY, 2)); diff --git a/src/ngTouch/swipe.js b/src/ngTouch/swipe.js index 884e0800d83c..ff5416b2d51b 100644 --- a/src/ngTouch/swipe.js +++ b/src/ngTouch/swipe.js @@ -40,11 +40,9 @@ ngTouch.factory('$swipe', [function() { }; function getCoordinates(event) { - var touches = event.touches && event.touches.length ? event.touches : [event]; - var e = (event.changedTouches && event.changedTouches[0]) || - (event.originalEvent && event.originalEvent.changedTouches && - event.originalEvent.changedTouches[0]) || - touches[0].originalEvent || touches[0]; + var originalEvent = event.originalEvent || event; + var touches = originalEvent.touches && originalEvent.touches.length ? originalEvent.touches : [originalEvent]; + var e = (originalEvent.changedTouches && originalEvent.changedTouches[0]) || touches[0]; return { x: e.clientX, diff --git a/test/ngTouch/directive/ngClickSpec.js b/test/ngTouch/directive/ngClickSpec.js index 921c64578b2b..53b34db37dea 100644 --- a/test/ngTouch/directive/ngClickSpec.js +++ b/test/ngTouch/directive/ngClickSpec.js @@ -5,8 +5,8 @@ describe('ngClick (touch)', function() { // TODO(braden): Once we have other touch-friendly browsers on CI, allow them here. // Currently Firefox and IE refuse to fire touch events. - var chrome = /chrome/.test(navigator.userAgent.toLowerCase()); - if (!chrome) { + // Enable iPhone for manual testing. + if (!/chrome|iphone/i.test(navigator.userAgent)) { return; } @@ -48,6 +48,34 @@ describe('ngClick (touch)', function() { expect($rootScope.event).toBeDefined(); })); + if (window.jQuery) { + it('should not unwrap a jQuery-wrapped event object on click', inject(function($rootScope, $compile) { + element = $compile('
')($rootScope); + $rootScope.$digest(); + + browserTrigger(element, 'click', { + keys: [], + x: 10, + y: 10 + }); + expect($rootScope.event.originalEvent).toBeDefined(); + expect($rootScope.event.originalEvent.clientX).toBe(10); + expect($rootScope.event.originalEvent.clientY).toBe(10); + })); + + it('should not unwrap a jQuery-wrapped event object on touchstart/touchend', + inject(function($rootScope, $compile, $rootElement) { + element = $compile('
')($rootScope); + $rootElement.append(element); + $rootScope.$digest(); + + browserTrigger(element, 'touchstart'); + browserTrigger(element, 'touchend'); + + expect($rootScope.event.originalEvent).toBeDefined(); + })); + } + it('should not click if the touch is held too long', inject(function($rootScope, $compile, $rootElement) { element = $compile('
')($rootScope); @@ -463,6 +491,17 @@ describe('ngClick (touch)', function() { expect($rootScope.selection).toBe('initial'); }); + + + it('should blur the other element on click', function() { + var blurSpy = spyOn(otherElement, 'blur'); + touch(otherElement, 10, 10); + + time = 500; + click(label, 10, 10); + + expect(blurSpy).toHaveBeenCalled(); + }); }); }); diff --git a/test/ngTouch/swipeSpec.js b/test/ngTouch/swipeSpec.js index 416d9f5d632d..1135ba3c19d8 100644 --- a/test/ngTouch/swipeSpec.js +++ b/test/ngTouch/swipeSpec.js @@ -67,8 +67,8 @@ describe('$swipe', function() { if (restrictBrowsers) { // TODO(braden): Once we have other touch-friendly browsers on CI, allow them here. // Currently Firefox and IE refuse to fire touch events. - var chrome = /chrome/.test(navigator.userAgent.toLowerCase()); - if (!chrome) { + // Enable iPhone for manual testing. + if (!/chrome|iphone/i.test(navigator.userAgent)) { return; } } From 7e91cc523fd682d9a31c8e0ecd56e6d0ec5f090e Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Mon, 13 Oct 2014 14:41:22 +0300 Subject: [PATCH 174/489] feat($anchorScroll): allow scrolling to a specified element Add an optional argument to `$anchorScroll()` to enable scrolling to an anchor element different than that related to the current value of `$location.hash()`. If the argument is omitted or is not a string, the value of `$location.hash()` will be used instead. Closes #4568 Closes #9596 --- src/ng/anchorScroll.js | 15 ++-- test/ng/anchorScrollSpec.js | 135 +++++++++++++++++++++++++++--------- 2 files changed, 112 insertions(+), 38 deletions(-) diff --git a/src/ng/anchorScroll.js b/src/ng/anchorScroll.js index baaac2f3fda0..a4b25dff56fc 100644 --- a/src/ng/anchorScroll.js +++ b/src/ng/anchorScroll.js @@ -38,9 +38,10 @@ function $AnchorScrollProvider() { * @requires $rootScope * * @description - * When called, it checks the current value of {@link ng.$location#hash $location.hash()} and - * scrolls to the related element, according to the rules specified in the - * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document). + * When called, it scrolls to the element related to the specified `hash` or (if omitted) to the + * current value of {@link ng.$location#hash $location.hash()}, according to the rules specified + * in the + * [HTML5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document). * * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to * match any anchor whenever it changes. This can be disabled by calling @@ -49,6 +50,9 @@ function $AnchorScrollProvider() { * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a * vertical scroll-offset (either fixed or dynamic). * + * @param {string=} hash The hash specifying the element to scroll to. If omitted, the value of + * {@link ng.$location#hash $location.hash()} will be used. + * * @property {(number|function|jqLite)} yOffset * If set, specifies a vertical scroll-offset. This is often useful when there are fixed * positioned elements at the top of the page, such as navbars, headers etc. @@ -232,8 +236,9 @@ function $AnchorScrollProvider() { } } - function scroll() { - var hash = $location.hash(), elm; + function scroll(hash) { + hash = isString(hash) ? hash : $location.hash(); + var elm; // empty hash, scroll to the top of the page if (!hash) scrollTo(null); diff --git a/test/ng/anchorScrollSpec.js b/test/ng/anchorScrollSpec.js index 63213458e55e..24490b4e0d03 100644 --- a/test/ng/anchorScrollSpec.js +++ b/test/ng/anchorScrollSpec.js @@ -23,7 +23,6 @@ describe('$anchorScroll', function() { }; } - function addElements() { var elements = sliceArgs(arguments); @@ -49,9 +48,9 @@ describe('$anchorScroll', function() { }; } - function callAnchorScroll() { + function callAnchorScroll(hash) { return function($anchorScroll) { - $anchorScroll(); + $anchorScroll(hash); }; } @@ -141,50 +140,120 @@ describe('$anchorScroll', function() { beforeEach(createMockWindow()); - it('should scroll to top of the window if empty hash', inject( - changeHashAndScroll(''), - expectScrollingToTop)); + describe('and implicitly using `$location.hash()`', function() { + + it('should scroll to top of the window if empty hash', inject( + changeHashAndScroll(''), + expectScrollingToTop)); + + + it('should not scroll if hash does not match any element', inject( + addElements('id=one', 'id=two'), + changeHashAndScroll('non-existing'), + expectNoScrolling())); + + + it('should scroll to anchor element with name', inject( + addElements('a name=abc'), + changeHashAndScroll('abc'), + expectScrollingTo('a name=abc'))); + + + it('should not scroll to other than anchor element with name', inject( + addElements('input name=xxl', 'select name=xxl', 'form name=xxl'), + changeHashAndScroll('xxl'), + expectNoScrolling())); + + + it('should scroll to anchor even if other element with given name exist', inject( + addElements('input name=some', 'a name=some'), + changeHashAndScroll('some'), + expectScrollingTo('a name=some'))); + + + it('should scroll to element with id with precedence over name', inject( + addElements('name=abc', 'id=abc'), + changeHashAndScroll('abc'), + expectScrollingTo('id=abc'))); - it('should not scroll if hash does not match any element', inject( - addElements('id=one', 'id=two'), - changeHashAndScroll('non-existing'), - expectNoScrolling())); + it('should scroll to top if hash == "top" and no matching element', inject( + changeHashAndScroll('top'), + expectScrollingToTop)); - it('should scroll to anchor element with name', inject( - addElements('a name=abc'), - changeHashAndScroll('abc'), - expectScrollingTo('a name=abc'))); + it('should scroll to element with id "top" if present', inject( + addElements('id=top'), + changeHashAndScroll('top'), + expectScrollingTo('id=top'))); + }); + + + describe('and specifying a hash', function() { + + it('should ignore the `hash` argument if not a string', inject( + spyOnJQLiteDocumentLoaded(), + addElements('id=one', 'id=two'), + changeHashTo('one'), // won't scroll since `jqLiteDocumentLoaded()` is spied upon + callAnchorScroll({}), + expectScrollingTo('id=one'), + unspyOnJQLiteDocumentLoaded())); + + + it('should ignore `$location.hash()` if `hash` is passed as argument', inject( + spyOnJQLiteDocumentLoaded(), + addElements('id=one', 'id=two'), + changeHashTo('one'), // won't scroll since `jqLiteDocumentLoaded()` is spied upon + callAnchorScroll('two'), + expectScrollingTo('id=two'), + unspyOnJQLiteDocumentLoaded())); + + it('should scroll to top of the window if empty hash', inject( + callAnchorScroll(''), + expectScrollingToTop)); - it('should not scroll to other than anchor element with name', inject( - addElements('input name=xxl', 'select name=xxl', 'form name=xxl'), - changeHashAndScroll('xxl'), - expectNoScrolling())); + it('should not scroll if hash does not match any element', inject( + addElements('id=one', 'id=two'), + callAnchorScroll('non-existing'), + expectNoScrolling())); - it('should scroll to anchor even if other element with given name exist', inject( - addElements('input name=some', 'a name=some'), - changeHashAndScroll('some'), - expectScrollingTo('a name=some'))); + it('should scroll to anchor element with name', inject( + addElements('a name=abc'), + callAnchorScroll('abc'), + expectScrollingTo('a name=abc'))); - it('should scroll to element with id with precedence over name', inject( - addElements('name=abc', 'id=abc'), - changeHashAndScroll('abc'), - expectScrollingTo('id=abc'))); + it('should not scroll to other than anchor element with name', inject( + addElements('input name=xxl', 'select name=xxl', 'form name=xxl'), + callAnchorScroll('xxl'), + expectNoScrolling())); - it('should scroll to top if hash == "top" and no matching element', inject( - changeHashAndScroll('top'), - expectScrollingToTop)); + it('should scroll to anchor even if other element with given name exist', inject( + addElements('input name=some', 'a name=some'), + callAnchorScroll('some'), + expectScrollingTo('a name=some'))); - it('should scroll to element with id "top" if present', inject( - addElements('id=top'), - changeHashAndScroll('top'), - expectScrollingTo('id=top'))); + + it('should scroll to element with id with precedence over name', inject( + addElements('name=abc', 'id=abc'), + callAnchorScroll('abc'), + expectScrollingTo('id=abc'))); + + + it('should scroll to top if hash == "top" and no matching element', inject( + callAnchorScroll('top'), + expectScrollingToTop)); + + + it('should scroll to element with id "top" if present', inject( + addElements('id=top'), + callAnchorScroll('top'), + expectScrollingTo('id=top'))); + }); }); From 91cf48f7c9e85982bc3cc0becbcc701338330b26 Mon Sep 17 00:00:00 2001 From: Pawel Kozlowski Date: Mon, 30 Mar 2015 15:37:04 +0200 Subject: [PATCH 175/489] feat($http): support custom params serializers Closes #3740 Closes #7429 Closes #9224 Closes #11461 --- src/AngularPublic.js | 4 ++ src/ng/http.js | 109 +++++++++++++++++++++++++++++++++---------- test/ng/httpSpec.js | 73 ++++++++++++++++++++++++++++- 3 files changed, 160 insertions(+), 26 deletions(-) diff --git a/src/AngularPublic.js b/src/AngularPublic.js index 814a12519799..9a7b182f669b 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -67,6 +67,8 @@ $IntervalProvider, $$HashMapProvider, $HttpProvider, + $HttpParamSerializerProvider, + $HttpParamSerializerJQLikeProvider, $HttpBackendProvider, $LocationProvider, $LogProvider, @@ -224,6 +226,8 @@ function publishExternalAPI(angular) { $interpolate: $InterpolateProvider, $interval: $IntervalProvider, $http: $HttpProvider, + $httpParamSerializer: $HttpParamSerializerProvider, + $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, $httpBackend: $HttpBackendProvider, $location: $LocationProvider, $log: $LogProvider, diff --git a/src/ng/http.js b/src/ng/http.js index 83f596286c49..0e56afad8586 100644 --- a/src/ng/http.js +++ b/src/ng/http.js @@ -9,6 +9,64 @@ var JSON_ENDS = { }; var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/; +function paramSerializerFactory(jQueryMode) { + + function serializeValue(v) { + if (isObject(v)) { + return isDate(v) ? v.toISOString() : toJson(v); + } + return v; + } + + return function paramSerializer(params) { + if (!params) return ''; + var parts = []; + forEachSorted(params, function(value, key) { + if (value === null || isUndefined(value)) return; + if (isArray(value) || isObject(value) && jQueryMode) { + forEach(value, function(v, k) { + var keySuffix = jQueryMode ? '[' + (!isArray(value) ? k : '') + ']' : ''; + parts.push(encodeUriQuery(key + keySuffix) + '=' + encodeUriQuery(serializeValue(v))); + }); + } else { + parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(value))); + } + }); + + return parts.length > 0 ? parts.join('&') : ''; + }; +} + +function $HttpParamSerializerProvider() { + /** + * @ngdoc service + * @name $httpParamSerializer + * @description + * + * Default $http params serializer that converts objects to a part of a request URL + * according to the following rules: + * * `{'foo': 'bar'}` results in `foo=bar` + * * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object) + * * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element) + * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D"` (stringified and encoded representation of an object) + * */ + this.$get = function() { + return paramSerializerFactory(false); + }; +} + +function $HttpParamSerializerJQLikeProvider() { + /** + * @ngdoc service + * @name $httpParamSerializerJQLike + * + * Alternative $http params serializer that follows jQuerys `param()` method {http://api.jquery.com/jquery.param/} logic. + * */ + this.$get = function() { + return paramSerializerFactory(true); + }; +} + function defaultHttpResponseTransform(data, headers) { if (isString(data)) { // Strip json vulnerability protection prefix and trim whitespace @@ -153,6 +211,11 @@ function $HttpProvider() { * - **`defaults.headers.put`** * - **`defaults.headers.patch`** * + * - **`defaults.paramSerializer`** - {string|function(Object):string} - A function used to prepare string representation + * of request parameters (specified as an object). + * Is specified as string, it is interpreted as function registered in with the {$injector}. + * Defaults to {$httpParamSerializer}. + * **/ var defaults = this.defaults = { // transform incoming response data @@ -174,7 +237,9 @@ function $HttpProvider() { }, xsrfCookieName: 'XSRF-TOKEN', - xsrfHeaderName: 'X-XSRF-TOKEN' + xsrfHeaderName: 'X-XSRF-TOKEN', + + paramSerializer: '$httpParamSerializer' }; var useApplyAsync = false; @@ -188,7 +253,7 @@ function $HttpProvider() { * significant performance improvement for bigger applications that make many HTTP requests * concurrently (common during application bootstrap). * - * Defaults to false. If no value is specifed, returns the current configured value. + * Defaults to false. If no value is specified, returns the current configured value. * * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred * "apply" on the next tick, giving time for subsequent requests in a roughly ~10ms window @@ -225,6 +290,12 @@ function $HttpProvider() { var defaultCache = $cacheFactory('$http'); + /** + * Make sure that default param serializer is exposed as a function + */ + defaults.paramSerializer = isString(defaults.paramSerializer) ? + $injector.get(defaults.paramSerializer) : defaults.paramSerializer; + /** * Interceptors stored in reverse order. Inner interceptors before outer interceptors. * The reversal is needed so that we can build up the interception chain around the @@ -636,6 +707,9 @@ function $HttpProvider() { * response body, headers and status and returns its transformed (typically deserialized) version. * See {@link ng.$http#overriding-the-default-transformations-per-request * Overriding the Default Transformations} + * - **paramSerializer** - {string|function(Object):string} - A function used to prepare string representation + * of request parameters (specified as an object). + * Is specified as string, it is interpreted as function registered in with the {$injector}. * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the * GET request, otherwise if a cache instance built with * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for @@ -764,11 +838,14 @@ function $HttpProvider() { var config = extend({ method: 'get', transformRequest: defaults.transformRequest, - transformResponse: defaults.transformResponse + transformResponse: defaults.transformResponse, + paramSerializer: defaults.paramSerializer }, requestConfig); config.headers = mergeHeaders(requestConfig); config.method = uppercase(config.method); + config.paramSerializer = isString(config.paramSerializer) ? + $injector.get(config.paramSerializer) : config.paramSerializer; var serverRequest = function(config) { var headers = config.headers; @@ -1032,7 +1109,7 @@ function $HttpProvider() { cache, cachedResp, reqHeaders = config.headers, - url = buildUrl(config.url, config.params); + url = buildUrl(config.url, config.paramSerializer(config.params)); $http.pendingRequests.push(config); promise.then(removePendingReq, removePendingReq); @@ -1139,27 +1216,9 @@ function $HttpProvider() { } - function buildUrl(url, params) { - if (!params) return url; - var parts = []; - forEachSorted(params, function(value, key) { - if (value === null || isUndefined(value)) return; - if (!isArray(value)) value = [value]; - - forEach(value, function(v) { - if (isObject(v)) { - if (isDate(v)) { - v = v.toISOString(); - } else { - v = toJson(v); - } - } - parts.push(encodeUriQuery(key) + '=' + - encodeUriQuery(v)); - }); - }); - if (parts.length > 0) { - url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&'); + function buildUrl(url, serializedParams) { + if (serializedParams.length > 0) { + url += ((url.indexOf('?') == -1) ? '?' : '&') + serializedParams; } return url; } diff --git a/test/ng/httpSpec.js b/test/ng/httpSpec.js index a858c83c64bc..a73f2ae75e5f 100644 --- a/test/ng/httpSpec.js +++ b/test/ng/httpSpec.js @@ -3,6 +3,9 @@ describe('$http', function() { var callback, mockedCookies; + var customParamSerializer = function(params) { + return Object.keys(params).join('_'); + }; beforeEach(function() { callback = jasmine.createSpy('done'); @@ -14,6 +17,9 @@ describe('$http', function() { }); }); + beforeEach(module({ + customParamSerializer: customParamSerializer + })); beforeEach(module(function($exceptionHandlerProvider) { $exceptionHandlerProvider.mode('log'); })); @@ -354,6 +360,20 @@ describe('$http', function() { $httpBackend.expect('GET', '/url?date=2014-07-15T17:30:00.000Z').respond(''); $http({url: '/url', params: {date:new Date('2014-07-15T17:30:00.000Z')}, method: 'GET'}); }); + + + describe('custom params serialization', function() { + + it('should allow specifying custom paramSerializer as function', function() { + $httpBackend.expect('GET', '/url?foo_bar').respond(''); + $http({url: '/url', params: {foo: 'fooVal', bar: 'barVal'}, paramSerializer: customParamSerializer}); + }); + + it('should allow specifying custom paramSerializer as function from DI', function() { + $httpBackend.expect('GET', '/url?foo_bar').respond(''); + $http({url: '/url', params: {foo: 'fooVal', bar: 'barVal'}, paramSerializer: 'customParamSerializer'}); + }); + }); }); @@ -1788,11 +1808,16 @@ describe('$http', function() { $httpBackend.flush(); }); - it('should have separate opbjects for defaults PUT and POST', function() { + it('should have separate objects for defaults PUT and POST', function() { expect($http.defaults.headers.post).not.toBe($http.defaults.headers.put); expect($http.defaults.headers.post).not.toBe($http.defaults.headers.patch); expect($http.defaults.headers.put).not.toBe($http.defaults.headers.patch); }); + + it('should expose default param serializer at runtime', function() { + var paramSerializer = $http.defaults.paramSerializer; + expect(paramSerializer({foo: 'foo', bar: ['bar', 'baz']})).toEqual('bar=bar&bar=baz&foo=foo'); + }); }); }); @@ -1929,3 +1954,49 @@ describe('$http with $applyAsync', function() { expect(log).toEqual(['response 1', 'response 2', 'response 3']); }); }); + +describe('$http param serializers', function() { + + var defSer, jqrSer; + beforeEach(inject(function($httpParamSerializer, $httpParamSerializerJQLike) { + defSer = $httpParamSerializer; + jqrSer = $httpParamSerializerJQLike; + })); + + describe('common functionality', function() { + + it('should return empty string for null or undefined params', function() { + expect(defSer(undefined)).toEqual(''); + expect(jqrSer(undefined)).toEqual(''); + expect(defSer(null)).toEqual(''); + expect(jqrSer(null)).toEqual(''); + }); + + it('should serialize objects', function() { + expect(defSer({foo: 'foov', bar: 'barv'})).toEqual('bar=barv&foo=foov'); + expect(jqrSer({foo: 'foov', bar: 'barv'})).toEqual('bar=barv&foo=foov'); + }); + + }); + + describe('default array serialization', function() { + + it('should serialize arrays by repeating param name', function() { + expect(defSer({a: 'b', foo: ['bar', 'baz']})).toEqual('a=b&foo=bar&foo=baz'); + }); + }); + + describe('jquery array and objects serialization', function() { + + it('should serialize arrays by repeating param name with [] suffix', function() { + expect(jqrSer({a: 'b', foo: ['bar', 'baz']})).toEqual('a=b&foo%5B%5D=bar&foo%5B%5D=baz'); + expect(decodeURIComponent(jqrSer({a: 'b', foo: ['bar', 'baz']}))).toEqual('a=b&foo[]=bar&foo[]=baz'); + }); + + it('should serialize objects by repeating param name with [kay] suffix', function() { + expect(jqrSer({a: 'b', foo: {'bar': 'barv', 'baz': 'bazv'}})).toEqual('a=b&foo%5Bbar%5D=barv&foo%5Bbaz%5D=bazv'); + //a=b&foo[bar]=barv&foo[baz]=bazv + }); + }); + +}); From 197ed8153b2c6d61b2ad1ee4b46c67b64181fd8a Mon Sep 17 00:00:00 2001 From: Pawel Kozlowski Date: Thu, 2 Apr 2015 19:46:10 +0200 Subject: [PATCH 176/489] docs($http): fix $httpParamSerializerJQLike description --- src/ng/http.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ng/http.js b/src/ng/http.js index 0e56afad8586..75991b20c57c 100644 --- a/src/ng/http.js +++ b/src/ng/http.js @@ -59,6 +59,7 @@ function $HttpParamSerializerJQLikeProvider() { /** * @ngdoc service * @name $httpParamSerializerJQLike + * @description * * Alternative $http params serializer that follows jQuerys `param()` method {http://api.jquery.com/jquery.param/} logic. * */ From 40453d2e2940a72ae1151af2181fa9ddb5c19e40 Mon Sep 17 00:00:00 2001 From: mustela Date: Tue, 31 Mar 2015 19:07:59 -0300 Subject: [PATCH 177/489] fix($resource) add @ support for properties names Add support for properties that starts with @. This is useful when working with BadgerFish convention. Closes #10533 Closes #11473 --- src/ngResource/resource.js | 2 +- test/ngResource/resourceSpec.js | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ngResource/resource.js b/src/ngResource/resource.js index 3a48705ae68b..52531bd37a68 100644 --- a/src/ngResource/resource.js +++ b/src/ngResource/resource.js @@ -5,7 +5,7 @@ var $resourceMinErr = angular.$$minErr('$resource'); // Helper functions and regex to lookup a dotted path on an object // stopping at undefined/null. The path must be composed of ASCII // identifiers (just like $parse) -var MEMBER_NAME_REGEX = /^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/; +var MEMBER_NAME_REGEX = /^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/; function isValidDottedPath(path) { return (path != null && path !== '' && path !== 'hasOwnProperty' && diff --git a/test/ngResource/resourceSpec.js b/test/ngResource/resourceSpec.js index 813a75659df7..7ab87fa7d16a 100644 --- a/test/ngResource/resourceSpec.js +++ b/test/ngResource/resourceSpec.js @@ -44,6 +44,7 @@ describe("resource", function() { expect(isValidDottedPath('1abc')).toBe(false); expect(isValidDottedPath('.')).toBe(false); expect(isValidDottedPath('$')).toBe(true); + expect(isValidDottedPath('@')).toBe(true); expect(isValidDottedPath('a')).toBe(true); expect(isValidDottedPath('A')).toBe(true); expect(isValidDottedPath('a1')).toBe(true); @@ -53,12 +54,14 @@ describe("resource", function() { expect(isValidDottedPath('$.$')).toBe(true); expect(isValidDottedPath('.$')).toBe(false); expect(isValidDottedPath('$.')).toBe(false); + expect(isValidDottedPath('@.')).toBe(false); + expect(isValidDottedPath('.@')).toBe(false); }); }); describe('lookupDottedPath', function() { /* global lookupDottedPath: false */ - var data = {a: {b: 'foo', c: null}}; + var data = {a: {b: 'foo', c: null, '@d':'d-foo'},'@b':'b-foo'}; it('should throw for invalid path', function() { expect(function() { @@ -68,9 +71,11 @@ describe("resource", function() { }); it('should get dotted paths', function() { - expect(lookupDottedPath(data, 'a')).toEqual({b: 'foo', c: null}); + expect(lookupDottedPath(data, 'a')).toEqual({b: 'foo', c: null, '@d':'d-foo'}); expect(lookupDottedPath(data, 'a.b')).toBe('foo'); expect(lookupDottedPath(data, 'a.c')).toBeNull(); + expect(lookupDottedPath(data, 'a.@d')).toBe('d-foo'); + expect(lookupDottedPath(data, '@b')).toBe('b-foo'); }); it('should skip over null/undefined members', function() { From 9c0c78975721bbf708feb741f37a5f34cbb9bb69 Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Thu, 2 Apr 2015 19:16:21 +0300 Subject: [PATCH 178/489] test(browerTrigger): ensure touch events initialize correctly on touch enabled Chrome MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On certain browsers (e.g. on desktop Chrome with touch-events enabled), using the `initTouchEvent()` method (introduced in 06a9f0a) did not correctly initialize the event, nor did the event get dispatched on the target element. Using the `Event` constructor and manually attaching a `TouchList`, works around the issue (although not a proper fix). Fixes #11471 Closes #11493 --- src/ngScenario/browserTrigger.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/ngScenario/browserTrigger.js b/src/ngScenario/browserTrigger.js index bcbdb27acc29..f3c22fe5ff62 100644 --- a/src/ngScenario/browserTrigger.js +++ b/src/ngScenario/browserTrigger.js @@ -134,17 +134,15 @@ } function createTouchEvent(element, eventType, x, y) { - var evnt = document.createEvent('TouchEvent'); + var evnt = new Event(eventType); x = x || 0; y = y || 0; var touch = document.createTouch(window, element, Date.now(), x, y, x, y); var touches = document.createTouchList(touch); - var targetTouches = document.createTouchList(touch); - var changedTouches = document.createTouchList(touch); - evnt.initTouchEvent(eventType, true, true, window, null, 0, 0, 0, 0, false, false, false, false, - touches, targetTouches, changedTouches, 1, 0); + evnt.touches = touches; + return evnt; } }()); From 3ee26531c810f8ac5b66ab29a48712f9638a7bf8 Mon Sep 17 00:00:00 2001 From: David Li Date: Tue, 4 Nov 2014 12:25:07 -0500 Subject: [PATCH 179/489] perf($rootScope): remove history event handler when app is torn down Remember the popstate and hashchange handler registered with window when the application bootstraps, and remove it when the application is torn down Closes #9897 Closes #9905 --- src/ng/browser.js | 10 ++++++++++ src/ng/rootScope.js | 5 +++++ src/ngMock/angular-mocks.js | 1 + test/ng/browserSpecs.js | 17 +++++++++++++++++ test/ng/rootScopeSpec.js | 7 +++++++ 5 files changed, 40 insertions(+) diff --git a/src/ng/browser.js b/src/ng/browser.js index dc8d691d5872..a698302edce2 100644 --- a/src/ng/browser.js +++ b/src/ng/browser.js @@ -264,6 +264,16 @@ function Browser(window, document, $log, $sniffer) { return callback; }; + /** + * @private + * Remove popstate and hashchange handler from window. + * + * NOTE: this api is intended for use only by $rootScope. + */ + self.$$applicationDestroyed = function() { + jqLite(window).off('hashchange popstate', cacheStateAndFireUrlChange); + }; + /** * Checks whether the url has changed outside of Angular. * Needs to be exported to be able to check for changes that have been done in sync, diff --git a/src/ng/rootScope.js b/src/ng/rootScope.js index fc915b6ab037..c2310a1f11a3 100644 --- a/src/ng/rootScope.js +++ b/src/ng/rootScope.js @@ -878,6 +878,11 @@ function $RootScopeProvider() { this.$broadcast('$destroy'); this.$$destroyed = true; + if (this === $rootScope) { + //Remove handlers attached to window when $rootScope is removed + $browser.$$applicationDestroyed(); + } + incrementWatchersCount(this, -this.$$watchersCount); for (var eventName in this.$$listenerCount) { decrementListenerCount(this, this.$$listenerCount[eventName], eventName); diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index fd29efaf0f07..6208a9fdb4cc 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -57,6 +57,7 @@ angular.mock.$Browser = function() { return listener; }; + self.$$applicationDestroyed = angular.noop; self.$$checkUrlChange = angular.noop; self.deferredFns = []; diff --git a/test/ng/browserSpecs.js b/test/ng/browserSpecs.js index 3166a08a3599..4e987645c86a 100755 --- a/test/ng/browserSpecs.js +++ b/test/ng/browserSpecs.js @@ -647,6 +647,23 @@ describe('browser', function() { }; } }); + + + it("should stop calling callbacks when application has been torn down", function() { + sniffer.history = true; + browser.onUrlChange(callback); + fakeWindow.location.href = 'http://server/new'; + + browser.$$applicationDestroyed(); + + fakeWindow.fire('popstate'); + expect(callback).not.toHaveBeenCalled(); + + fakeWindow.fire('hashchange'); + fakeWindow.setTimeout.flush(); + expect(callback).not.toHaveBeenCalled(); + }); + }); diff --git a/test/ng/rootScopeSpec.js b/test/ng/rootScopeSpec.js index 7e145826538b..3e405b2006b5 100644 --- a/test/ng/rootScopeSpec.js +++ b/test/ng/rootScopeSpec.js @@ -1048,6 +1048,13 @@ describe('Scope', function() { })); + it('should call $browser.$$applicationDestroyed when destroying rootScope', inject(function($rootScope, $browser) { + spyOn($browser, '$$applicationDestroyed'); + $rootScope.$destroy(); + expect($browser.$$applicationDestroyed).toHaveBeenCalledOnce(); + })); + + it('should remove first', inject(function($rootScope) { first.$destroy(); $rootScope.$digest(); From a27baa32b29f52b9f9816d98d59560795a812fcb Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Thu, 2 Apr 2015 21:46:04 +0100 Subject: [PATCH 180/489] style($browserSpec): fix typo --- test/ng/browserSpecs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ng/browserSpecs.js b/test/ng/browserSpecs.js index 4e987645c86a..ddfd06f45840 100755 --- a/test/ng/browserSpecs.js +++ b/test/ng/browserSpecs.js @@ -189,7 +189,7 @@ describe('browser', function() { } }); - describe('outstading requests', function() { + describe('outstanding requests', function() { it('should process callbacks immedietly with no outstanding requests', function() { var callback = jasmine.createSpy('callback'); browser.notifyWhenNoOutstandingRequests(callback); From 9e72357441ee79f85cec30e9ad2c8195bc91468f Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Thu, 2 Apr 2015 22:32:22 +0100 Subject: [PATCH 181/489] docs(toJson): improve option param documentation With an upgrade to dgeni-packages 0.10.13, this style of optional param is rendered more correctly. See #11095 --- src/Angular.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Angular.js b/src/Angular.js index 5dd0a4b5927d..eaccab1fbc32 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -1081,8 +1081,8 @@ function toJsonReplacer(key, value) { * stripped since angular uses this notation internally. * * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON. - * @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace. - * If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2). + * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace. + * If set to an integer, the JSON output will contain that many spaces per indentation. * @returns {string|undefined} JSON-ified string representing `obj`. */ function toJson(obj, pretty) { From 344d9fcd4dba425cad8ea177ff5f3a7c767b0976 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Thu, 2 Apr 2015 22:41:03 +0100 Subject: [PATCH 182/489] chore(dependencies): general update (including new dgeni-packages) Closes #11095 --- npm-shrinkwrap.clean.json | 660 +++--- npm-shrinkwrap.json | 4706 +++++++++++++++++++------------------ 2 files changed, 2849 insertions(+), 2517 deletions(-) diff --git a/npm-shrinkwrap.clean.json b/npm-shrinkwrap.clean.json index 09eed0e1929e..20165cc88f5c 100644 --- a/npm-shrinkwrap.clean.json +++ b/npm-shrinkwrap.clean.json @@ -4,19 +4,19 @@ "version": "0.2.2", "dependencies": { "bootstrap": { - "version": "3.3.2" + "version": "3.3.4" }, "express": { - "version": "4.11.2", + "version": "4.12.3", "dependencies": { "accepts": { - "version": "1.2.4", + "version": "1.2.5", "dependencies": { "mime-types": { - "version": "2.0.9", + "version": "2.0.10", "dependencies": { "mime-db": { - "version": "1.7.0" + "version": "1.8.0" } } }, @@ -28,14 +28,20 @@ "content-disposition": { "version": "0.5.0" }, + "content-type": { + "version": "1.0.1" + }, + "cookie": { + "version": "0.1.2" + }, "cookie-signature": { - "version": "1.0.5" + "version": "1.0.6" }, "debug": { - "version": "2.1.1", + "version": "2.1.3", "dependencies": { "ms": { - "version": "0.6.2" + "version": "0.7.0" } } }, @@ -54,13 +60,13 @@ } }, "finalhandler": { - "version": "0.3.3" + "version": "0.3.4" }, "fresh": { "version": "0.2.4" }, - "media-typer": { - "version": "0.3.0" + "merge-descriptors": { + "version": "1.0.0" }, "methods": { "version": "1.1.1" @@ -80,30 +86,30 @@ "version": "0.1.3" }, "proxy-addr": { - "version": "1.0.6", + "version": "1.0.7", "dependencies": { "forwarded": { "version": "0.1.0" }, "ipaddr.js": { - "version": "0.1.8" + "version": "0.1.9" } } }, "qs": { - "version": "2.3.3" + "version": "2.4.1" }, "range-parser": { "version": "1.0.2" }, "send": { - "version": "0.11.1", + "version": "0.12.2", "dependencies": { "destroy": { "version": "1.0.3" }, "mime": { - "version": "1.2.11" + "version": "1.3.4" }, "ms": { "version": "0.7.0" @@ -111,16 +117,19 @@ } }, "serve-static": { - "version": "1.8.1" + "version": "1.9.2" }, "type-is": { - "version": "1.5.7", + "version": "1.6.1", "dependencies": { + "media-typer": { + "version": "0.3.0" + }, "mime-types": { - "version": "2.0.9", + "version": "2.0.10", "dependencies": { "mime-db": { - "version": "1.7.0" + "version": "1.8.0" } } } @@ -129,19 +138,13 @@ "vary": { "version": "1.0.0" }, - "cookie": { - "version": "0.1.2" - }, - "merge-descriptors": { - "version": "0.0.2" - }, "utils-merge": { "version": "1.0.0" } } }, "minimist": { - "version": "1.1.0" + "version": "1.1.1" }, "mkdirp": { "version": "0.5.0", @@ -152,10 +155,52 @@ } }, "rimraf": { - "version": "2.2.8" + "version": "2.3.2", + "dependencies": { + "glob": { + "version": "4.5.3", + "dependencies": { + "inflight": { + "version": "1.0.4", + "dependencies": { + "wrappy": { + "version": "1.0.1" + } + } + }, + "inherits": { + "version": "2.0.1" + }, + "minimatch": { + "version": "2.0.4", + "dependencies": { + "brace-expansion": { + "version": "1.1.0", + "dependencies": { + "balanced-match": { + "version": "0.2.0" + }, + "concat-map": { + "version": "0.0.1" + } + } + } + } + }, + "once": { + "version": "1.3.1", + "dependencies": { + "wrappy": { + "version": "1.0.1" + } + } + } + } + } + } }, "underscore": { - "version": "1.8.1" + "version": "1.8.3" }, "di": { "version": "2.0.0-pre-9", @@ -165,7 +210,12 @@ "resolved": "git+https://github.com/vojtajina/traceur-compiler#d90b1e34c799bf61cd1aafdc33db0a554fa9e617", "dependencies": { "commander": { - "version": "2.6.0" + "version": "2.7.1", + "dependencies": { + "graceful-readlink": { + "version": "1.0.1" + } + } }, "q-io": { "version": "1.10.9", @@ -260,10 +310,10 @@ } }, "browser-resolve": { - "version": "1.7.0", + "version": "1.8.2", "dependencies": { "resolve": { - "version": "1.1.0" + "version": "1.1.6" } } }, @@ -271,7 +321,7 @@ "version": "0.1.4", "dependencies": { "pako": { - "version": "0.2.5" + "version": "0.2.6" } } }, @@ -323,7 +373,7 @@ "version": "0.0.1" }, "crypto-browserify": { - "version": "3.9.12", + "version": "3.9.13", "dependencies": { "browserify-aes": { "version": "1.0.0" @@ -370,7 +420,7 @@ } }, "create-ecdh": { - "version": "1.0.3", + "version": "2.0.0", "dependencies": { "bn.js": { "version": "1.3.0" @@ -389,7 +439,7 @@ } }, "create-hash": { - "version": "1.1.0", + "version": "1.1.1", "dependencies": { "ripemd160": { "version": "1.0.0" @@ -422,16 +472,16 @@ "version": "3.0.2" }, "public-encrypt": { - "version": "1.1.2", + "version": "2.0.0", "dependencies": { "bn.js": { "version": "1.3.0" }, "browserify-rsa": { - "version": "1.1.1" + "version": "2.0.0" }, "parse-asn1": { - "version": "2.0.0", + "version": "3.0.0", "dependencies": { "asn1.js": { "version": "1.0.3", @@ -440,12 +490,6 @@ "version": "1.0.0" } } - }, - "asn1.js-rfc3280": { - "version": "1.0.0" - }, - "pemstrip": { - "version": "0.0.1" } } } @@ -493,7 +537,7 @@ "version": "1.0.2" }, "glob": { - "version": "4.4.0", + "version": "4.5.3", "dependencies": { "inflight": { "version": "1.0.4", @@ -504,7 +548,7 @@ } }, "minimatch": { - "version": "2.0.1", + "version": "2.0.4", "dependencies": { "brace-expansion": { "version": "1.1.0", @@ -544,7 +588,7 @@ "version": "2.0.1" }, "insert-module-globals": { - "version": "6.2.0", + "version": "6.2.1", "dependencies": { "JSONStream": { "version": "0.7.4", @@ -632,7 +676,7 @@ } }, "module-deps": { - "version": "3.7.2", + "version": "3.7.5", "dependencies": { "JSONStream": { "version": "0.7.4", @@ -655,13 +699,13 @@ "version": "1.6.1", "dependencies": { "estraverse": { - "version": "1.9.1" + "version": "1.9.3" }, "esutils": { "version": "1.1.6" }, "esprima": { - "version": "1.2.4" + "version": "1.2.5" }, "optionator": { "version": "0.5.0", @@ -710,7 +754,7 @@ } }, "resolve": { - "version": "1.1.3" + "version": "1.1.6" }, "stream-combiner2": { "version": "1.0.2", @@ -841,10 +885,10 @@ } }, "timers-browserify": { - "version": "1.3.0", + "version": "1.4.0", "dependencies": { "process": { - "version": "0.10.0" + "version": "0.10.1" } } }, @@ -895,7 +939,7 @@ "version": "2.3.6" }, "uglify-js": { - "version": "2.4.16", + "version": "2.4.19", "dependencies": { "async": { "version": "0.2.10" @@ -908,9 +952,18 @@ } } }, - "optimist": { - "version": "0.3.7", + "yargs": { + "version": "3.5.4", "dependencies": { + "camelcase": { + "version": "1.0.2" + }, + "decamelize": { + "version": "1.0.0" + }, + "window-size": { + "version": "0.1.0" + }, "wordwrap": { "version": "0.0.2" } @@ -924,10 +977,13 @@ } }, "url": { - "version": "0.10.2", + "version": "0.10.3", "dependencies": { "punycode": { "version": "1.3.2" + }, + "querystring": { + "version": "0.2.0" } } }, @@ -1004,7 +1060,7 @@ "version": "0.2.2" }, "bower-registry-client": { - "version": "0.2.3", + "version": "0.2.4", "dependencies": { "async": { "version": "0.2.10" @@ -1053,10 +1109,10 @@ "version": "0.9.0" }, "mime-types": { - "version": "2.0.9", + "version": "2.0.10", "dependencies": { "mime-db": { - "version": "1.7.0" + "version": "1.8.0" } } } @@ -1069,7 +1125,7 @@ "version": "1.0.2" }, "node-uuid": { - "version": "1.4.2" + "version": "1.4.3" }, "qs": { "version": "2.3.3" @@ -1163,7 +1219,7 @@ "version": "1.1.0" }, "escape-string-regexp": { - "version": "1.0.2" + "version": "1.0.3" }, "has-ansi": { "version": "0.1.0", @@ -1256,7 +1312,7 @@ "version": "2.0.1" }, "minimatch": { - "version": "2.0.1", + "version": "2.0.4", "dependencies": { "brace-expansion": { "version": "1.1.0", @@ -1298,7 +1354,7 @@ } }, "graceful-fs": { - "version": "3.0.5" + "version": "3.0.6" }, "handlebars": { "version": "2.0.0", @@ -1333,7 +1389,7 @@ "version": "0.7.1", "dependencies": { "cli-color": { - "version": "0.3.2", + "version": "0.3.3", "dependencies": { "d": { "version": "0.1.1" @@ -1402,14 +1458,14 @@ "version": "2.0.1", "dependencies": { "ansi-regex": { - "version": "1.1.0" + "version": "1.1.1" } } } } }, "rx": { - "version": "2.4.0" + "version": "2.4.9" }, "through": { "version": "2.3.6" @@ -1429,7 +1485,7 @@ "version": "1.1.0" }, "escape-string-regexp": { - "version": "1.0.2" + "version": "1.0.3" }, "has-ansi": { "version": "0.1.0", @@ -1459,10 +1515,10 @@ "version": "3.2.7", "dependencies": { "argparse": { - "version": "1.0.1", + "version": "1.0.2", "dependencies": { "lodash": { - "version": "3.2.0" + "version": "3.6.0" }, "sprintf-js": { "version": "1.0.2" @@ -1492,7 +1548,7 @@ "version": "0.6.0", "dependencies": { "cli-color": { - "version": "0.3.2", + "version": "0.3.3", "dependencies": { "d": { "version": "0.1.1" @@ -1558,14 +1614,14 @@ "version": "2.0.1", "dependencies": { "ansi-regex": { - "version": "1.1.0" + "version": "1.1.1" } } } } }, "rx": { - "version": "2.4.0" + "version": "2.4.9" }, "through": { "version": "2.3.6" @@ -1606,7 +1662,7 @@ "version": "1.0.0", "dependencies": { "minimist": { - "version": "1.1.0" + "version": "1.1.1" } } }, @@ -1629,7 +1685,7 @@ "version": "1.0.0" }, "junk": { - "version": "1.0.0" + "version": "1.0.1" }, "lockfile": { "version": "1.0.0" @@ -1719,7 +1775,7 @@ "version": "1.0.2" }, "node-uuid": { - "version": "1.4.2" + "version": "1.4.3" }, "tunnel-agent": { "version": "0.4.0" @@ -1811,7 +1867,7 @@ "version": "2.3.2" }, "shell-quote": { - "version": "1.4.2", + "version": "1.4.3", "dependencies": { "jsonify": { "version": "0.0.0" @@ -1828,7 +1884,7 @@ } }, "stringify-object": { - "version": "1.0.0" + "version": "1.0.1" }, "tar-fs": { "version": "0.5.2", @@ -1910,10 +1966,10 @@ "version": "3.2.7", "dependencies": { "argparse": { - "version": "1.0.1", + "version": "1.0.2", "dependencies": { "lodash": { - "version": "3.2.0" + "version": "3.6.0" }, "sprintf-js": { "version": "1.0.2" @@ -2011,7 +2067,7 @@ } }, "which": { - "version": "1.0.8" + "version": "1.0.9" } } }, @@ -2025,7 +2081,7 @@ "version": "0.1.31", "dependencies": { "graceful-fs": { - "version": "3.0.5" + "version": "3.0.6" }, "inherits": { "version": "2.0.1" @@ -2039,7 +2095,46 @@ } }, "rimraf": { - "version": "2.2.8" + "version": "2.3.2", + "dependencies": { + "glob": { + "version": "4.5.3", + "dependencies": { + "inflight": { + "version": "1.0.4", + "dependencies": { + "wrappy": { + "version": "1.0.1" + } + } + }, + "minimatch": { + "version": "2.0.4", + "dependencies": { + "brace-expansion": { + "version": "1.1.0", + "dependencies": { + "balanced-match": { + "version": "0.2.0" + }, + "concat-map": { + "version": "0.0.1" + } + } + } + } + }, + "once": { + "version": "1.3.1", + "dependencies": { + "wrappy": { + "version": "1.0.1" + } + } + } + } + } + } } } }, @@ -2118,7 +2213,7 @@ "version": "1.4.3", "dependencies": { "domelementtype": { - "version": "1.1.3" + "version": "1.3.0" } } } @@ -2137,7 +2232,7 @@ "version": "1.5.1" }, "domelementtype": { - "version": "1.1.3" + "version": "1.3.0" }, "readable-stream": { "version": "1.1.13", @@ -2257,7 +2352,7 @@ } }, "node-uuid": { - "version": "1.4.2" + "version": "1.4.3" }, "cookie-jar": { "version": "0.2.0" @@ -2290,13 +2385,23 @@ } }, "dgeni-packages": { - "version": "0.10.10", + "version": "0.10.13", "dependencies": { "catharsis": { - "version": "0.7.1" + "version": "0.8.6", + "dependencies": { + "underscore-contrib": { + "version": "0.3.0", + "dependencies": { + "underscore": { + "version": "1.6.0" + } + } + } + } }, "change-case": { - "version": "2.2.0", + "version": "2.3.0", "dependencies": { "camel-case": { "version": "1.1.1" @@ -2316,6 +2421,9 @@ "lower-case": { "version": "1.1.2" }, + "lower-case-first": { + "version": "1.0.0" + }, "param-case": { "version": "1.1.1" }, @@ -2341,15 +2449,15 @@ "version": "1.1.2" }, "upper-case-first": { - "version": "1.1.0" + "version": "1.1.1" } } }, "esprima": { - "version": "1.2.4" + "version": "1.2.5" }, "estraverse": { - "version": "1.9.1" + "version": "1.9.3" }, "glob": { "version": "3.2.11", @@ -2371,6 +2479,9 @@ "dom-serializer": { "version": "0.1.0", "dependencies": { + "domelementtype": { + "version": "1.1.3" + }, "entities": { "version": "1.1.1" } @@ -2379,7 +2490,7 @@ } }, "domelementtype": { - "version": "1.1.3" + "version": "1.3.0" }, "readable-stream": { "version": "1.1.13", @@ -2415,7 +2526,7 @@ } }, "nunjucks": { - "version": "1.0.7", + "version": "1.2.0", "dependencies": { "optimist": { "version": "0.6.1", @@ -2429,19 +2540,54 @@ } }, "chokidar": { - "version": "0.8.4", + "version": "0.12.6", "dependencies": { + "readdirp": { + "version": "1.3.0", + "dependencies": { + "graceful-fs": { + "version": "2.0.3" + }, + "minimatch": { + "version": "0.2.14", + "dependencies": { + "lru-cache": { + "version": "2.5.0" + }, + "sigmund": { + "version": "1.0.0" + } + } + }, + "readable-stream": { + "version": "1.0.33", + "dependencies": { + "core-util-is": { + "version": "1.0.1" + }, + "isarray": { + "version": "0.0.1" + }, + "string_decoder": { + "version": "0.10.31" + }, + "inherits": { + "version": "2.0.1" + } + } + } + } + }, + "async-each": { + "version": "0.1.6" + }, "fsevents": { - "version": "0.2.1", - "resolved": "git+https://github.com/pipobscure/fsevents#7dcdf9fa3f8956610fd6f69f72c67bace2de7138", + "version": "0.3.5", "dependencies": { "nan": { - "version": "0.8.0" + "version": "1.5.3" } } - }, - "recursive-readdir": { - "version": "0.0.2" } } } @@ -2530,7 +2676,7 @@ } }, "node-uuid": { - "version": "1.4.2" + "version": "1.4.3" }, "cookie-jar": { "version": "0.2.0" @@ -2679,7 +2825,7 @@ "version": "2.2.1" }, "which": { - "version": "1.0.8" + "version": "1.0.9" }, "js-yaml": { "version": "2.0.5", @@ -2820,7 +2966,7 @@ "version": "0.1.6", "dependencies": { "crc32-stream": { - "version": "0.3.2" + "version": "0.3.3" } } } @@ -2835,7 +2981,7 @@ "version": "1.1.0" }, "escape-string-regexp": { - "version": "1.0.2" + "version": "1.0.3" }, "has-ansi": { "version": "0.1.0", @@ -3117,7 +3263,7 @@ "version": "1.1.0" }, "escape-string-regexp": { - "version": "1.0.2" + "version": "1.0.3" }, "has-ansi": { "version": "0.1.0", @@ -3149,7 +3295,7 @@ "version": "2.5.11", "dependencies": { "cli": { - "version": "0.6.5", + "version": "0.6.6", "dependencies": { "glob": { "version": "3.2.11", @@ -3195,6 +3341,9 @@ "dom-serializer": { "version": "0.1.0", "dependencies": { + "domelementtype": { + "version": "1.1.3" + }, "entities": { "version": "1.1.1" } @@ -3203,7 +3352,7 @@ } }, "domelementtype": { - "version": "1.1.3" + "version": "1.3.0" }, "readable-stream": { "version": "1.1.13", @@ -3255,7 +3404,7 @@ "version": "0.0.6", "dependencies": { "bluebird": { - "version": "2.9.12" + "version": "2.9.24" }, "win-spawn": { "version": "2.0.0" @@ -3282,13 +3431,13 @@ "version": "2.5.1" }, "esprima": { - "version": "1.2.4" + "version": "1.2.5" }, "esprima-harmony-jscs": { "version": "1.1.0-regex-token-fix" }, "estraverse": { - "version": "1.9.1" + "version": "1.9.3" }, "exit": { "version": "0.1.2" @@ -3297,7 +3446,7 @@ "version": "4.0.6", "dependencies": { "graceful-fs": { - "version": "3.0.5" + "version": "3.0.6" }, "inherits": { "version": "2.0.1" @@ -3324,7 +3473,7 @@ } }, "minimatch": { - "version": "2.0.1", + "version": "2.0.4", "dependencies": { "brace-expansion": { "version": "1.1.0", @@ -3346,13 +3495,13 @@ "version": "0.3.4", "dependencies": { "node-uuid": { - "version": "1.4.2" + "version": "1.4.3" }, "vow-queue": { "version": "0.4.1" }, "glob": { - "version": "4.4.0", + "version": "4.5.3", "dependencies": { "inflight": { "version": "1.0.4", @@ -3386,12 +3535,12 @@ } }, "supports-color": { - "version": "1.2.0" + "version": "1.2.1" } } }, "vow": { - "version": "0.4.8" + "version": "0.4.9" } } }, @@ -3399,35 +3548,38 @@ "version": "0.0.2" }, "grunt-shell": { - "version": "1.1.1", + "version": "1.1.2", "dependencies": { "chalk": { - "version": "0.5.1", + "version": "1.0.0", "dependencies": { "ansi-styles": { - "version": "1.1.0" + "version": "2.0.1" }, "escape-string-regexp": { - "version": "1.0.2" + "version": "1.0.3" }, "has-ansi": { - "version": "0.1.0", + "version": "1.0.3", "dependencies": { "ansi-regex": { - "version": "0.2.1" + "version": "1.1.1" + }, + "get-stdin": { + "version": "4.0.1" } } }, "strip-ansi": { - "version": "0.3.0", + "version": "2.0.1", "dependencies": { "ansi-regex": { - "version": "0.2.1" + "version": "1.1.1" } } }, "supports-color": { - "version": "0.2.0" + "version": "1.3.1" } } } @@ -3446,7 +3598,7 @@ "version": "1.1.0" }, "escape-string-regexp": { - "version": "1.0.2" + "version": "1.0.3" }, "has-ansi": { "version": "0.1.0", @@ -3476,10 +3628,10 @@ "version": "0.3.10" }, "liftoff": { - "version": "2.0.1", + "version": "2.0.3", "dependencies": { "extend": { - "version": "1.3.0" + "version": "2.0.0" }, "findup-sync": { "version": "0.2.1", @@ -3499,7 +3651,7 @@ "version": "2.0.1" }, "minimatch": { - "version": "2.0.1", + "version": "2.0.4", "dependencies": { "brace-expansion": { "version": "1.1.0", @@ -3530,12 +3682,12 @@ "version": "0.3.1" }, "resolve": { - "version": "1.0.0" + "version": "1.1.6" } } }, "minimist": { - "version": "1.1.0" + "version": "1.1.1" }, "orchestrator": { "version": "0.3.7", @@ -3565,7 +3717,7 @@ "version": "0.2.2" }, "semver": { - "version": "4.3.0" + "version": "4.3.3" }, "tildify": { "version": "1.0.0", @@ -3576,13 +3728,18 @@ } }, "v8flags": { - "version": "2.0.2" + "version": "2.0.3", + "dependencies": { + "user-home": { + "version": "1.1.1" + } + } }, "vinyl-fs": { "version": "0.3.13", "dependencies": { "defaults": { - "version": "1.0.0", + "version": "1.0.2", "dependencies": { "clone": { "version": "0.1.19" @@ -3593,7 +3750,7 @@ "version": "3.1.18", "dependencies": { "glob": { - "version": "4.4.0", + "version": "4.5.3", "dependencies": { "inflight": { "version": "1.0.4", @@ -3617,7 +3774,7 @@ } }, "minimatch": { - "version": "2.0.1", + "version": "2.0.4", "dependencies": { "brace-expansion": { "version": "1.1.0", @@ -3658,7 +3815,7 @@ "version": "0.1.0", "dependencies": { "lodash": { - "version": "1.0.1" + "version": "1.0.2" }, "glob": { "version": "3.1.21", @@ -3689,7 +3846,7 @@ } }, "graceful-fs": { - "version": "3.0.5" + "version": "3.0.6" }, "mkdirp": { "version": "0.5.0", @@ -3751,13 +3908,13 @@ } }, "gulp-concat": { - "version": "2.5.1", + "version": "2.5.2", "dependencies": { "concat-with-sourcemaps": { - "version": "1.0.0", + "version": "1.0.2", "dependencies": { "source-map": { - "version": "0.1.43", + "version": "0.4.2", "dependencies": { "amdefine": { "version": "0.1.0" @@ -3806,7 +3963,7 @@ "version": "1.1.0" }, "escape-string-regexp": { - "version": "1.0.2" + "version": "1.0.3" }, "has-ansi": { "version": "0.1.0", @@ -3836,7 +3993,7 @@ "version": "4.0.1" }, "meow": { - "version": "3.0.0", + "version": "3.1.0", "dependencies": { "camelcase-keys": { "version": "1.0.0", @@ -3863,7 +4020,7 @@ } }, "minimist": { - "version": "1.1.0" + "version": "1.1.1" }, "object-assign": { "version": "2.0.0" @@ -4031,7 +4188,7 @@ "version": "0.4.5", "dependencies": { "glob": { - "version": "4.4.0", + "version": "5.0.3", "dependencies": { "inflight": { "version": "1.0.4", @@ -4045,7 +4202,7 @@ "version": "2.0.1" }, "minimatch": { - "version": "2.0.1", + "version": "2.0.4", "dependencies": { "brace-expansion": { "version": "1.1.0", @@ -4093,7 +4250,7 @@ "version": "1.1.6" }, "domelementtype": { - "version": "1.1.3" + "version": "1.3.0" }, "readable-stream": { "version": "1.0.33", @@ -4132,7 +4289,7 @@ "version": "1.1.0" }, "escape-string-regexp": { - "version": "1.0.2" + "version": "1.0.3" }, "has-ansi": { "version": "0.1.0", @@ -4162,7 +4319,7 @@ "version": "4.0.1" }, "meow": { - "version": "3.0.0", + "version": "3.1.0", "dependencies": { "camelcase-keys": { "version": "1.0.0", @@ -4189,7 +4346,7 @@ } }, "minimist": { - "version": "1.1.0" + "version": "1.1.1" }, "object-assign": { "version": "2.0.0" @@ -4516,11 +4673,28 @@ } }, "gulp-rename": { - "version": "1.2.0" + "version": "1.2.2" }, "gulp-sourcemaps": { - "version": "1.3.0", + "version": "1.5.1", "dependencies": { + "convert-source-map": { + "version": "1.0.0" + }, + "graceful-fs": { + "version": "3.0.6" + }, + "strip-bom": { + "version": "1.0.0", + "dependencies": { + "first-chunk-stream": { + "version": "1.0.0" + }, + "is-utf8": { + "version": "0.2.0" + } + } + }, "through2": { "version": "0.6.3", "dependencies": { @@ -4556,9 +4730,6 @@ "version": "0.0.1" } } - }, - "convert-source-map": { - "version": "0.4.1" } } }, @@ -4636,7 +4807,7 @@ } }, "gulp-util": { - "version": "3.0.3", + "version": "3.0.4", "dependencies": { "array-differ": { "version": "1.0.0" @@ -4648,32 +4819,35 @@ "version": "1.0.0" }, "chalk": { - "version": "0.5.1", + "version": "1.0.0", "dependencies": { "ansi-styles": { - "version": "1.1.0" + "version": "2.0.1" }, "escape-string-regexp": { - "version": "1.0.2" + "version": "1.0.3" }, "has-ansi": { - "version": "0.1.0", + "version": "1.0.3", "dependencies": { "ansi-regex": { - "version": "0.2.1" + "version": "1.1.1" + }, + "get-stdin": { + "version": "4.0.1" } } }, "strip-ansi": { - "version": "0.3.0", + "version": "2.0.1", "dependencies": { "ansi-regex": { - "version": "0.2.1" + "version": "1.1.1" } } }, "supports-color": { - "version": "0.2.0" + "version": "1.3.1" } } }, @@ -4684,7 +4858,7 @@ "version": "4.0.1" }, "meow": { - "version": "3.0.0", + "version": "3.1.0", "dependencies": { "camelcase-keys": { "version": "1.0.0", @@ -4714,32 +4888,17 @@ } } }, - "lodash.reescape": { - "version": "3.0.1", - "dependencies": { - "lodash._reescape": { - "version": "3.0.0" - } - } + "lodash._reescape": { + "version": "3.0.0" }, - "lodash.reevaluate": { - "version": "3.0.1", - "dependencies": { - "lodash._reevaluate": { - "version": "3.0.0" - } - } + "lodash._reevaluate": { + "version": "3.0.0" }, - "lodash.reinterpolate": { - "version": "3.0.1", - "dependencies": { - "lodash._reinterpolate": { - "version": "3.0.0" - } - } + "lodash._reinterpolate": { + "version": "3.0.0" }, "lodash.template": { - "version": "3.3.0", + "version": "3.4.0", "dependencies": { "lodash._basecopy": { "version": "3.0.0" @@ -4751,35 +4910,35 @@ "version": "3.0.0" }, "lodash._isiterateecall": { - "version": "3.0.2" - }, - "lodash._reinterpolate": { - "version": "3.0.0" + "version": "3.0.5" }, "lodash.escape": { "version": "3.0.0" }, "lodash.keys": { - "version": "3.0.3", + "version": "3.0.5", "dependencies": { "lodash.isarguments": { - "version": "3.0.0" + "version": "3.0.1" }, "lodash.isarray": { - "version": "3.0.0" + "version": "3.0.1" }, "lodash.isnative": { - "version": "3.0.0" + "version": "3.0.1" } } }, + "lodash.restparam": { + "version": "3.6.0" + }, "lodash.templatesettings": { "version": "3.1.0" } } }, "minimist": { - "version": "1.1.0" + "version": "1.1.1" }, "multipipe": { "version": "0.1.2", @@ -4867,13 +5026,13 @@ } }, "requirejs": { - "version": "2.1.16" + "version": "2.1.17" }, "walkdir": { "version": "0.0.7" }, "underscore": { - "version": "1.8.1" + "version": "1.8.3" }, "gaze": { "version": "0.3.4", @@ -4929,40 +5088,43 @@ } }, "jshint-stylish": { - "version": "1.0.0", + "version": "1.0.1", "dependencies": { "chalk": { - "version": "0.5.1", + "version": "1.0.0", "dependencies": { "ansi-styles": { - "version": "1.1.0" + "version": "2.0.1" }, "escape-string-regexp": { - "version": "1.0.2" + "version": "1.0.3" }, "has-ansi": { - "version": "0.1.0", + "version": "1.0.3", "dependencies": { "ansi-regex": { - "version": "0.2.1" + "version": "1.1.1" + }, + "get-stdin": { + "version": "4.0.1" } } }, "strip-ansi": { - "version": "0.3.0", + "version": "2.0.1", "dependencies": { "ansi-regex": { - "version": "0.2.1" + "version": "1.1.1" } } }, "supports-color": { - "version": "0.2.0" + "version": "1.3.1" } } }, "log-symbols": { - "version": "1.0.1" + "version": "1.0.2" }, "string-length": { "version": "1.0.0", @@ -4971,7 +5133,7 @@ "version": "2.0.1", "dependencies": { "ansi-regex": { - "version": "1.1.0" + "version": "1.1.1" } } } @@ -4989,7 +5151,7 @@ "version": "0.0.1" }, "socket.io": { - "version": "1.3.4", + "version": "1.3.5", "dependencies": { "engine.io": { "version": "1.5.1", @@ -5050,7 +5212,7 @@ } }, "socket.io-parser": { - "version": "2.2.3", + "version": "2.2.4", "dependencies": { "debug": { "version": "0.7.4" @@ -5067,7 +5229,7 @@ } }, "socket.io-client": { - "version": "1.3.4", + "version": "1.3.5", "dependencies": { "debug": { "version": "0.7.4" @@ -5276,43 +5438,8 @@ } }, "chokidar": { - "version": "1.0.0-rc3", + "version": "0.12.6", "dependencies": { - "anymatch": { - "version": "1.1.0", - "dependencies": { - "minimatch": { - "version": "1.0.0", - "dependencies": { - "lru-cache": { - "version": "2.5.0" - }, - "sigmund": { - "version": "1.0.0" - } - } - } - } - }, - "async-each": { - "version": "0.1.6" - }, - "glob-parent": { - "version": "1.0.0", - "dependencies": { - "is-glob": { - "version": "0.3.0" - } - } - }, - "is-binary-path": { - "version": "1.0.0", - "dependencies": { - "binary-extensions": { - "version": "1.3.0" - } - } - }, "readdirp": { "version": "1.3.0", "dependencies": { @@ -5335,6 +5462,9 @@ } } }, + "async-each": { + "version": "0.1.6" + }, "fsevents": { "version": "0.3.5", "dependencies": { @@ -5418,7 +5548,7 @@ "version": "1.0.0" }, "i": { - "version": "0.3.2" + "version": "0.3.3" }, "mkdirp": { "version": "0.5.0", @@ -5546,10 +5676,10 @@ "version": "1.1.4", "dependencies": { "mime-types": { - "version": "2.0.9", + "version": "2.0.10", "dependencies": { "mime-db": { - "version": "1.7.0" + "version": "1.8.0" } } }, @@ -5562,7 +5692,7 @@ "version": "2.0.2", "dependencies": { "mime-db": { - "version": "1.7.0" + "version": "1.8.0" } } }, @@ -5635,10 +5765,10 @@ "version": "1.1.4", "dependencies": { "mime-types": { - "version": "2.0.9", + "version": "2.0.10", "dependencies": { "mime-db": { - "version": "1.7.0" + "version": "1.8.0" } } }, @@ -5786,10 +5916,10 @@ "version": "1.1.4", "dependencies": { "mime-types": { - "version": "2.0.9", + "version": "2.0.10", "dependencies": { "mime-db": { - "version": "1.7.0" + "version": "1.8.0" } } }, @@ -5848,10 +5978,10 @@ "version": "1.5.7", "dependencies": { "mime-types": { - "version": "2.0.9", + "version": "2.0.10", "dependencies": { "mime-db": { - "version": "1.7.0" + "version": "1.8.0" } } } @@ -5969,7 +6099,7 @@ "version": "4.0.6", "dependencies": { "graceful-fs": { - "version": "3.0.5" + "version": "3.0.6" }, "inherits": { "version": "2.0.1" @@ -6046,7 +6176,7 @@ "version": "0.1.6", "dependencies": { "crc32-stream": { - "version": "0.3.2" + "version": "0.3.3" } } } @@ -6114,7 +6244,7 @@ "version": "1.0.2" }, "node-uuid": { - "version": "1.4.2" + "version": "1.4.3" }, "qs": { "version": "1.2.2" @@ -6340,7 +6470,7 @@ } }, "sinon": { - "version": "1.12.2", + "version": "1.14.1", "dependencies": { "formatio": { "version": "1.1.1", @@ -6638,7 +6768,7 @@ "version": "1.0.1" }, "q-io": { - "version": "1.11.6", + "version": "1.12.0", "dependencies": { "qs": { "version": "1.2.2" diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 528e69c8e73f..e7769622ebc0 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -3,197 +3,212 @@ "dependencies": { "angular-benchpress": { "version": "0.2.2", - "from": "https://registry.npmjs.org/angular-benchpress/-/angular-benchpress-0.2.2.tgz", + "from": "angular-benchpress@>=0.0.0 <1.0.0", "resolved": "https://registry.npmjs.org/angular-benchpress/-/angular-benchpress-0.2.2.tgz", "dependencies": { "bootstrap": { - "version": "3.3.2", - "from": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.3.2.tgz", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.3.2.tgz" + "version": "3.3.4", + "from": "bootstrap@>=3.2.0 <4.0.0", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.3.4.tgz" }, "express": { - "version": "4.11.2", - "from": "https://registry.npmjs.org/express/-/express-4.11.2.tgz", - "resolved": "https://registry.npmjs.org/express/-/express-4.11.2.tgz", + "version": "4.12.3", + "from": "express@>=4.8.6 <5.0.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.12.3.tgz", "dependencies": { "accepts": { - "version": "1.2.4", - "from": "https://registry.npmjs.org/accepts/-/accepts-1.2.4.tgz", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.4.tgz", + "version": "1.2.5", + "from": "accepts@>=1.2.5 <1.3.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.5.tgz", "dependencies": { "mime-types": { - "version": "2.0.9", - "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", + "version": "2.0.10", + "from": "mime-types@>=2.0.10 <2.1.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.10.tgz", "dependencies": { "mime-db": { - "version": "1.7.0", - "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz" + "version": "1.8.0", + "from": "mime-db@>=1.8.0 <1.9.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.8.0.tgz" } } }, "negotiator": { "version": "0.5.1", - "from": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.1.tgz", + "from": "negotiator@0.5.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.1.tgz" } } }, "content-disposition": { "version": "0.5.0", - "from": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.0.tgz", + "from": "content-disposition@0.5.0", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.0.tgz" }, + "content-type": { + "version": "1.0.1", + "from": "content-type@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.1.tgz" + }, + "cookie": { + "version": "0.1.2", + "from": "cookie@0.1.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz" + }, "cookie-signature": { - "version": "1.0.5", - "from": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.5.tgz", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.5.tgz" + "version": "1.0.6", + "from": "cookie-signature@1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" }, "debug": { - "version": "2.1.1", - "from": "https://registry.npmjs.org/debug/-/debug-2.1.1.tgz", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.1.1.tgz", + "version": "2.1.3", + "from": "debug@>=2.1.3 <2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.1.3.tgz", "dependencies": { "ms": { - "version": "0.6.2", - "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" + "version": "0.7.0", + "from": "ms@0.7.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.0.tgz" } } }, "depd": { "version": "1.0.0", - "from": "https://registry.npmjs.org/depd/-/depd-1.0.0.tgz", + "from": "depd@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.0.tgz" }, "escape-html": { "version": "1.0.1", - "from": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz", + "from": "escape-html@1.0.1", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz" }, "etag": { "version": "1.5.1", - "from": "https://registry.npmjs.org/etag/-/etag-1.5.1.tgz", + "from": "etag@>=1.5.1 <1.6.0", "resolved": "https://registry.npmjs.org/etag/-/etag-1.5.1.tgz", "dependencies": { "crc": { "version": "3.2.1", - "from": "https://registry.npmjs.org/crc/-/crc-3.2.1.tgz", + "from": "crc@3.2.1", "resolved": "https://registry.npmjs.org/crc/-/crc-3.2.1.tgz" } } }, "finalhandler": { - "version": "0.3.3", - "from": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.3.3.tgz", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.3.3.tgz" + "version": "0.3.4", + "from": "finalhandler@0.3.4", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.3.4.tgz" }, "fresh": { "version": "0.2.4", - "from": "https://registry.npmjs.org/fresh/-/fresh-0.2.4.tgz", + "from": "fresh@0.2.4", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.4.tgz" }, - "media-typer": { - "version": "0.3.0", - "from": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + "merge-descriptors": { + "version": "1.0.0", + "from": "merge-descriptors@1.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.0.tgz" }, "methods": { "version": "1.1.1", - "from": "https://registry.npmjs.org/methods/-/methods-1.1.1.tgz", + "from": "methods@>=1.1.1 <1.2.0", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.1.tgz" }, "on-finished": { "version": "2.2.0", - "from": "https://registry.npmjs.org/on-finished/-/on-finished-2.2.0.tgz", + "from": "on-finished@>=2.2.0 <2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.2.0.tgz", "dependencies": { "ee-first": { "version": "1.1.0", - "from": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.0.tgz", + "from": "ee-first@1.1.0", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.0.tgz" } } }, "parseurl": { "version": "1.3.0", - "from": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz", + "from": "parseurl@>=1.3.0 <1.4.0", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz" }, "path-to-regexp": { "version": "0.1.3", - "from": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.3.tgz", + "from": "path-to-regexp@0.1.3", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.3.tgz" }, "proxy-addr": { - "version": "1.0.6", - "from": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.6.tgz", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.6.tgz", + "version": "1.0.7", + "from": "proxy-addr@>=1.0.7 <1.1.0", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.7.tgz", "dependencies": { "forwarded": { "version": "0.1.0", - "from": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", + "from": "forwarded@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" }, "ipaddr.js": { - "version": "0.1.8", - "from": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-0.1.8.tgz", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-0.1.8.tgz" + "version": "0.1.9", + "from": "ipaddr.js@0.1.9", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-0.1.9.tgz" } } }, "qs": { - "version": "2.3.3", - "from": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", - "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz" + "version": "2.4.1", + "from": "qs@2.4.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.4.1.tgz" }, "range-parser": { "version": "1.0.2", - "from": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz", + "from": "range-parser@>=1.0.2 <1.1.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz" }, "send": { - "version": "0.11.1", - "from": "https://registry.npmjs.org/send/-/send-0.11.1.tgz", - "resolved": "https://registry.npmjs.org/send/-/send-0.11.1.tgz", + "version": "0.12.2", + "from": "send@0.12.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.12.2.tgz", "dependencies": { "destroy": { "version": "1.0.3", - "from": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz", + "from": "destroy@1.0.3", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz" }, "mime": { - "version": "1.2.11", - "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" + "version": "1.3.4", + "from": "mime@1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" }, "ms": { "version": "0.7.0", - "from": "https://registry.npmjs.org/ms/-/ms-0.7.0.tgz", + "from": "ms@0.7.0", "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.0.tgz" } } }, "serve-static": { - "version": "1.8.1", - "from": "https://registry.npmjs.org/serve-static/-/serve-static-1.8.1.tgz", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.8.1.tgz" + "version": "1.9.2", + "from": "serve-static@>=1.9.2 <1.10.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.9.2.tgz" }, "type-is": { - "version": "1.5.7", - "from": "https://registry.npmjs.org/type-is/-/type-is-1.5.7.tgz", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.5.7.tgz", + "version": "1.6.1", + "from": "type-is@>=1.6.1 <1.7.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.1.tgz", "dependencies": { + "media-typer": { + "version": "0.3.0", + "from": "media-typer@0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + }, "mime-types": { - "version": "2.0.9", - "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", + "version": "2.0.10", + "from": "mime-types@>=2.0.10 <2.1.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.10.tgz", "dependencies": { "mime-db": { - "version": "1.7.0", - "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz" + "version": "1.8.0", + "from": "mime-db@>=1.8.0 <1.9.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.8.0.tgz" } } } @@ -201,106 +216,165 @@ }, "vary": { "version": "1.0.0", - "from": "https://registry.npmjs.org/vary/-/vary-1.0.0.tgz", + "from": "vary@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.0.tgz" }, - "cookie": { - "version": "0.1.2", - "from": "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz" - }, - "merge-descriptors": { - "version": "0.0.2", - "from": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-0.0.2.tgz", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-0.0.2.tgz" - }, "utils-merge": { "version": "1.0.0", - "from": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "from": "utils-merge@1.0.0", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" } } }, "minimist": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/minimist/-/minimist-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.0.tgz" + "version": "1.1.1", + "from": "minimist@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.1.tgz" }, "mkdirp": { "version": "0.5.0", - "from": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "from": "mkdirp@>=0.0.0 <1.0.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "from": "minimist@0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "rimraf": { - "version": "2.2.8", - "from": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" + "version": "2.3.2", + "from": "rimraf@>=2.2.8 <3.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.3.2.tgz", + "dependencies": { + "glob": { + "version": "4.5.3", + "from": "glob@>=4.4.2 <5.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "dependencies": { + "inflight": { + "version": "1.0.4", + "from": "inflight@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.1", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" + } + } + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + }, + "minimatch": { + "version": "2.0.4", + "from": "minimatch@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.4.tgz", + "dependencies": { + "brace-expansion": { + "version": "1.1.0", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", + "dependencies": { + "balanced-match": { + "version": "0.2.0", + "from": "balanced-match@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + } + } + } + } + }, + "once": { + "version": "1.3.1", + "from": "once@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.1", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" + } + } + } + } + } + } }, "underscore": { - "version": "1.8.1", - "from": "https://registry.npmjs.org/underscore/-/underscore-1.8.1.tgz", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.1.tgz" + "version": "1.8.3", + "from": "underscore@>=1.6.0 <2.0.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz" }, "di": { "version": "2.0.0-pre-9", - "from": "https://registry.npmjs.org/di/-/di-2.0.0-pre-9.tgz", + "from": "di@>=2.0.0-pre-9 <2.1.0", "resolved": "https://registry.npmjs.org/di/-/di-2.0.0-pre-9.tgz", "dependencies": { "traceur": { "version": "0.0.33", - "from": "traceur@git+https://github.com/vojtajina/traceur-compiler#d90b1e34c799bf61cd1aafdc33db0a554fa9e617", + "from": "../../../../../var/folders/gl/40dc6sj56mq3yzwyghl869vc0000gn/T/npm-67032-57ebb73e/git-cache-43943b72fafb/d90b1e34c799bf61cd1aafdc33db0a554fa9e617", "resolved": "git+https://github.com/vojtajina/traceur-compiler#d90b1e34c799bf61cd1aafdc33db0a554fa9e617", "dependencies": { "commander": { - "version": "2.6.0", - "from": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz" + "version": "2.7.1", + "from": "commander@>=1.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.7.1.tgz", + "dependencies": { + "graceful-readlink": { + "version": "1.0.1", + "from": "graceful-readlink@>=1.0.0", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" + } + } }, "q-io": { "version": "1.10.9", - "from": "https://registry.npmjs.org/q-io/-/q-io-1.10.9.tgz", + "from": "q-io@>=1.10.6 <1.11.0", "resolved": "https://registry.npmjs.org/q-io/-/q-io-1.10.9.tgz", "dependencies": { "q": { "version": "0.9.7", - "from": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "from": "q@>=0.9.7 <0.10.0", "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz" }, "qs": { "version": "0.1.0", - "from": "https://registry.npmjs.org/qs/-/qs-0.1.0.tgz", + "from": "qs@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/qs/-/qs-0.1.0.tgz" }, "url2": { "version": "0.0.0", - "from": "https://registry.npmjs.org/url2/-/url2-0.0.0.tgz", + "from": "url2@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/url2/-/url2-0.0.0.tgz" }, "mime": { "version": "1.2.11", - "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "from": "mime@>=1.2.11 <1.3.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "mimeparse": { "version": "0.1.4", - "from": "https://registry.npmjs.org/mimeparse/-/mimeparse-0.1.4.tgz", + "from": "mimeparse@>=0.1.4 <0.2.0", "resolved": "https://registry.npmjs.org/mimeparse/-/mimeparse-0.1.4.tgz" }, "collections": { "version": "0.2.2", - "from": "https://registry.npmjs.org/collections/-/collections-0.2.2.tgz", + "from": "collections@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/collections/-/collections-0.2.2.tgz", "dependencies": { "weak-map": { "version": "1.0.0", - "from": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.0.tgz", + "from": "weak-map@1.0.0", "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.0.tgz" } } @@ -311,66 +385,66 @@ }, "es6-shim": { "version": "0.9.3", - "from": "https://registry.npmjs.org/es6-shim/-/es6-shim-0.9.3.tgz", + "from": "es6-shim@>=0.9.2 <0.10.0", "resolved": "https://registry.npmjs.org/es6-shim/-/es6-shim-0.9.3.tgz" } } }, "rx": { "version": "2.3.25", - "from": "https://registry.npmjs.org/rx/-/rx-2.3.25.tgz", + "from": "rx@>=2.3.20 <2.4.0", "resolved": "https://registry.npmjs.org/rx/-/rx-2.3.25.tgz" }, "browserify": { "version": "7.0.3", - "from": "https://registry.npmjs.org/browserify/-/browserify-7.0.3.tgz", + "from": "browserify@>=7.0.0 <7.1.0", "resolved": "https://registry.npmjs.org/browserify/-/browserify-7.0.3.tgz", "dependencies": { "JSONStream": { "version": "0.8.4", - "from": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.8.4.tgz", + "from": "JSONStream@>=0.8.3 <0.9.0", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.8.4.tgz", "dependencies": { "jsonparse": { "version": "0.0.5", - "from": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "from": "jsonparse@0.0.5", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz" }, "through": { "version": "2.3.6", - "from": "https://registry.npmjs.org/through/-/through-2.3.6.tgz", + "from": "through@>=2.2.7 <3.0.0", "resolved": "https://registry.npmjs.org/through/-/through-2.3.6.tgz" } } }, "assert": { "version": "1.1.2", - "from": "https://registry.npmjs.org/assert/-/assert-1.1.2.tgz", + "from": "assert@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/assert/-/assert-1.1.2.tgz" }, "browser-pack": { "version": "3.2.0", - "from": "https://registry.npmjs.org/browser-pack/-/browser-pack-3.2.0.tgz", + "from": "browser-pack@>=3.2.0 <4.0.0", "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-3.2.0.tgz", "dependencies": { "combine-source-map": { "version": "0.3.0", - "from": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.3.0.tgz", + "from": "combine-source-map@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.3.0.tgz", "dependencies": { "inline-source-map": { "version": "0.3.1", - "from": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.3.1.tgz", + "from": "inline-source-map@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.3.1.tgz", "dependencies": { "source-map": { "version": "0.3.0", - "from": "https://registry.npmjs.org/source-map/-/source-map-0.3.0.tgz", + "from": "source-map@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.3.0.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", + "from": "amdefine@>=0.0.4", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } @@ -379,17 +453,17 @@ }, "convert-source-map": { "version": "0.3.5", - "from": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "from": "convert-source-map@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz" }, "source-map": { "version": "0.1.43", - "from": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "from": "source-map@>=0.1.31 <0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", + "from": "amdefine@>=0.0.4", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } @@ -398,85 +472,85 @@ }, "through2": { "version": "0.5.1", - "from": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "from": "through2@>=0.5.1 <0.6.0", "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz" } } }, "browser-resolve": { - "version": "1.7.0", - "from": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.7.0.tgz", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.7.0.tgz", + "version": "1.8.2", + "from": "browser-resolve@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.8.2.tgz", "dependencies": { "resolve": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/resolve/-/resolve-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.0.tgz" + "version": "1.1.6", + "from": "resolve@1.1.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.6.tgz" } } }, "browserify-zlib": { "version": "0.1.4", - "from": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "from": "browserify-zlib@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", "dependencies": { "pako": { - "version": "0.2.5", - "from": "https://registry.npmjs.org/pako/-/pako-0.2.5.tgz", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.5.tgz" + "version": "0.2.6", + "from": "pako@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.6.tgz" } } }, "buffer": { "version": "2.8.2", - "from": "https://registry.npmjs.org/buffer/-/buffer-2.8.2.tgz", + "from": "buffer@>=2.3.0 <3.0.0", "resolved": "https://registry.npmjs.org/buffer/-/buffer-2.8.2.tgz", "dependencies": { "base64-js": { "version": "0.0.7", - "from": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.7.tgz", + "from": "base64-js@0.0.7", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.7.tgz" }, "ieee754": { "version": "1.1.4", - "from": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.4.tgz", + "from": "ieee754@>=1.1.4 <2.0.0", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.4.tgz" }, "is-array": { "version": "1.0.1", - "from": "https://registry.npmjs.org/is-array/-/is-array-1.0.1.tgz", + "from": "is-array@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/is-array/-/is-array-1.0.1.tgz" } } }, "builtins": { "version": "0.0.7", - "from": "https://registry.npmjs.org/builtins/-/builtins-0.0.7.tgz", + "from": "builtins@>=0.0.3 <0.1.0", "resolved": "https://registry.npmjs.org/builtins/-/builtins-0.0.7.tgz" }, "commondir": { "version": "0.0.1", - "from": "https://registry.npmjs.org/commondir/-/commondir-0.0.1.tgz", + "from": "commondir@0.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-0.0.1.tgz" }, "concat-stream": { "version": "1.4.7", - "from": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.4.7.tgz", + "from": "concat-stream@>=1.4.1 <1.5.0", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.4.7.tgz", "dependencies": { "typedarray": { "version": "0.0.6", - "from": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "from": "typedarray@>=0.0.5 <0.1.0", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" }, "readable-stream": { "version": "1.1.13", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "from": "readable-stream@>=1.1.9 <1.2.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" } } @@ -485,88 +559,88 @@ }, "console-browserify": { "version": "1.1.0", - "from": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "from": "console-browserify@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "dependencies": { "date-now": { "version": "0.1.4", - "from": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "from": "date-now@>=0.1.4 <0.2.0", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz" } } }, "constants-browserify": { "version": "0.0.1", - "from": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-0.0.1.tgz", + "from": "constants-browserify@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-0.0.1.tgz" }, "crypto-browserify": { - "version": "3.9.12", - "from": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.9.12.tgz", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.9.12.tgz", + "version": "3.9.13", + "from": "crypto-browserify@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.9.13.tgz", "dependencies": { "browserify-aes": { "version": "1.0.0", - "from": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.0.tgz", + "from": "browserify-aes@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.0.tgz" }, "browserify-sign": { "version": "2.8.0", - "from": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-2.8.0.tgz", + "from": "browserify-sign@2.8.0", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-2.8.0.tgz", "dependencies": { "bn.js": { "version": "1.3.0", - "from": "https://registry.npmjs.org/bn.js/-/bn.js-1.3.0.tgz", + "from": "bn.js@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-1.3.0.tgz" }, "browserify-rsa": { "version": "1.1.1", - "from": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-1.1.1.tgz", + "from": "browserify-rsa@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-1.1.1.tgz" }, "elliptic": { "version": "1.0.1", - "from": "https://registry.npmjs.org/elliptic/-/elliptic-1.0.1.tgz", + "from": "elliptic@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-1.0.1.tgz", "dependencies": { "brorand": { "version": "1.0.5", - "from": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz", + "from": "brorand@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz" }, "hash.js": { "version": "1.0.2", - "from": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.2.tgz", + "from": "hash.js@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.2.tgz" } } }, "parse-asn1": { "version": "2.0.0", - "from": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-2.0.0.tgz", + "from": "parse-asn1@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-2.0.0.tgz", "dependencies": { "asn1.js": { "version": "1.0.3", - "from": "https://registry.npmjs.org/asn1.js/-/asn1.js-1.0.3.tgz", + "from": "asn1.js@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-1.0.3.tgz", "dependencies": { "minimalistic-assert": { "version": "1.0.0", - "from": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "from": "minimalistic-assert@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" } } }, "asn1.js-rfc3280": { "version": "1.0.0", - "from": "https://registry.npmjs.org/asn1.js-rfc3280/-/asn1.js-rfc3280-1.0.0.tgz", + "from": "asn1.js-rfc3280@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/asn1.js-rfc3280/-/asn1.js-rfc3280-1.0.0.tgz" }, "pemstrip": { "version": "0.0.1", - "from": "https://registry.npmjs.org/pemstrip/-/pemstrip-0.0.1.tgz", + "from": "pemstrip@0.0.1", "resolved": "https://registry.npmjs.org/pemstrip/-/pemstrip-0.0.1.tgz" } } @@ -574,28 +648,28 @@ } }, "create-ecdh": { - "version": "1.0.3", - "from": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-1.0.3.tgz", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-1.0.3.tgz", + "version": "2.0.0", + "from": "create-ecdh@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-2.0.0.tgz", "dependencies": { "bn.js": { "version": "1.3.0", - "from": "https://registry.npmjs.org/bn.js/-/bn.js-1.3.0.tgz", + "from": "bn.js@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-1.3.0.tgz" }, "elliptic": { "version": "1.0.1", - "from": "https://registry.npmjs.org/elliptic/-/elliptic-1.0.1.tgz", + "from": "elliptic@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-1.0.1.tgz", "dependencies": { "brorand": { "version": "1.0.5", - "from": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz", + "from": "brorand@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz" }, "hash.js": { "version": "1.0.2", - "from": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.2.tgz", + "from": "hash.js@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.2.tgz" } } @@ -603,45 +677,45 @@ } }, "create-hash": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.0.tgz", + "version": "1.1.1", + "from": "create-hash@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.1.tgz", "dependencies": { "ripemd160": { "version": "1.0.0", - "from": "https://registry.npmjs.org/ripemd160/-/ripemd160-1.0.0.tgz", + "from": "ripemd160@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-1.0.0.tgz" }, "sha.js": { "version": "2.3.6", - "from": "https://registry.npmjs.org/sha.js/-/sha.js-2.3.6.tgz", + "from": "sha.js@>=2.3.6 <3.0.0", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.3.6.tgz" } } }, "create-hmac": { "version": "1.1.3", - "from": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.3.tgz", + "from": "create-hmac@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.3.tgz" }, "diffie-hellman": { "version": "3.0.1", - "from": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-3.0.1.tgz", + "from": "diffie-hellman@>=3.0.1 <4.0.0", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-3.0.1.tgz", "dependencies": { "bn.js": { "version": "1.3.0", - "from": "https://registry.npmjs.org/bn.js/-/bn.js-1.3.0.tgz", + "from": "bn.js@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-1.3.0.tgz" }, "miller-rabin": { "version": "1.1.5", - "from": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-1.1.5.tgz", + "from": "miller-rabin@>=1.1.2 <2.0.0", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-1.1.5.tgz", "dependencies": { "brorand": { "version": "1.0.5", - "from": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz", + "from": "brorand@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz" } } @@ -650,50 +724,40 @@ }, "pbkdf2-compat": { "version": "3.0.2", - "from": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-3.0.2.tgz", + "from": "pbkdf2-compat@>=3.0.1 <4.0.0", "resolved": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-3.0.2.tgz" }, "public-encrypt": { - "version": "1.1.2", - "from": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-1.1.2.tgz", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-1.1.2.tgz", + "version": "2.0.0", + "from": "public-encrypt@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-2.0.0.tgz", "dependencies": { "bn.js": { "version": "1.3.0", - "from": "https://registry.npmjs.org/bn.js/-/bn.js-1.3.0.tgz", + "from": "bn.js@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-1.3.0.tgz" }, "browserify-rsa": { - "version": "1.1.1", - "from": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-1.1.1.tgz", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-1.1.1.tgz" + "version": "2.0.0", + "from": "browserify-rsa@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-2.0.0.tgz" }, "parse-asn1": { - "version": "2.0.0", - "from": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-2.0.0.tgz", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-2.0.0.tgz", + "version": "3.0.0", + "from": "parse-asn1@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-3.0.0.tgz", "dependencies": { "asn1.js": { "version": "1.0.3", - "from": "https://registry.npmjs.org/asn1.js/-/asn1.js-1.0.3.tgz", + "from": "asn1.js@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-1.0.3.tgz", "dependencies": { "minimalistic-assert": { "version": "1.0.0", - "from": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "from": "minimalistic-assert@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" } } - }, - "asn1.js-rfc3280": { - "version": "1.0.0", - "from": "https://registry.npmjs.org/asn1.js-rfc3280/-/asn1.js-rfc3280-1.0.0.tgz", - "resolved": "https://registry.npmjs.org/asn1.js-rfc3280/-/asn1.js-rfc3280-1.0.0.tgz" - }, - "pemstrip": { - "version": "0.0.1", - "from": "https://registry.npmjs.org/pemstrip/-/pemstrip-0.0.1.tgz", - "resolved": "https://registry.npmjs.org/pemstrip/-/pemstrip-0.0.1.tgz" } } } @@ -701,56 +765,56 @@ }, "randombytes": { "version": "2.0.1", - "from": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.1.tgz", + "from": "randombytes@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.1.tgz" } } }, "deep-equal": { "version": "0.2.2", - "from": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.2.tgz", + "from": "deep-equal@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.2.tgz" }, "defined": { "version": "0.0.0", - "from": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", + "from": "defined@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz" }, "deps-sort": { "version": "1.3.5", - "from": "https://registry.npmjs.org/deps-sort/-/deps-sort-1.3.5.tgz", + "from": "deps-sort@>=1.3.5 <2.0.0", "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-1.3.5.tgz", "dependencies": { "minimist": { "version": "0.2.0", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "from": "minimist@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz" }, "through2": { "version": "0.5.1", - "from": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "from": "through2@>=0.5.1 <0.6.0", "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz" } } }, "domain-browser": { "version": "1.1.4", - "from": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.4.tgz", + "from": "domain-browser@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.4.tgz" }, "duplexer2": { "version": "0.0.2", - "from": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "from": "duplexer2@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "dependencies": { "readable-stream": { "version": "1.1.13", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "from": "readable-stream@>=1.1.9 <1.2.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" } } @@ -759,44 +823,44 @@ }, "events": { "version": "1.0.2", - "from": "https://registry.npmjs.org/events/-/events-1.0.2.tgz", + "from": "events@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/events/-/events-1.0.2.tgz" }, "glob": { - "version": "4.4.0", - "from": "https://registry.npmjs.org/glob/-/glob-4.4.0.tgz", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.4.0.tgz", + "version": "4.5.3", + "from": "glob@>=4.0.5 <5.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", "dependencies": { "inflight": { "version": "1.0.4", - "from": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", + "from": "inflight@>=1.0.4 <2.0.0", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } }, "minimatch": { - "version": "2.0.1", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.1.tgz", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.1.tgz", + "version": "2.0.4", + "from": "minimatch@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.4.tgz", "dependencies": { "brace-expansion": { "version": "1.1.0", - "from": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", + "from": "brace-expansion@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", "dependencies": { "balanced-match": { "version": "0.2.0", - "from": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz", + "from": "balanced-match@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz" }, "concat-map": { "version": "0.0.1", - "from": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "from": "concat-map@0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" } } @@ -805,12 +869,12 @@ }, "once": { "version": "1.3.1", - "from": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "from": "once@>=1.3.0 <2.0.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -819,61 +883,61 @@ }, "http-browserify": { "version": "1.7.0", - "from": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz", + "from": "http-browserify@>=1.4.0 <2.0.0", "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz", "dependencies": { "Base64": { "version": "0.2.1", - "from": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz", + "from": "Base64@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz" } } }, "https-browserify": { "version": "0.0.0", - "from": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.0.tgz", + "from": "https-browserify@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.0.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "insert-module-globals": { - "version": "6.2.0", - "from": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-6.2.0.tgz", - "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-6.2.0.tgz", + "version": "6.2.1", + "from": "insert-module-globals@>=6.1.0 <7.0.0", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-6.2.1.tgz", "dependencies": { "JSONStream": { "version": "0.7.4", - "from": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.7.4.tgz", + "from": "JSONStream@>=0.7.1 <0.8.0", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.7.4.tgz", "dependencies": { "jsonparse": { "version": "0.0.5", - "from": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "from": "jsonparse@0.0.5", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz" } } }, "combine-source-map": { "version": "0.3.0", - "from": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.3.0.tgz", + "from": "combine-source-map@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.3.0.tgz", "dependencies": { "inline-source-map": { "version": "0.3.1", - "from": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.3.1.tgz", + "from": "inline-source-map@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.3.1.tgz", "dependencies": { "source-map": { "version": "0.3.0", - "from": "https://registry.npmjs.org/source-map/-/source-map-0.3.0.tgz", + "from": "source-map@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.3.0.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", + "from": "amdefine@>=0.0.4", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } @@ -882,17 +946,17 @@ }, "convert-source-map": { "version": "0.3.5", - "from": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "from": "convert-source-map@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz" }, "source-map": { "version": "0.1.43", - "from": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "from": "source-map@>=0.1.31 <0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", + "from": "amdefine@>=0.0.4", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } @@ -901,17 +965,17 @@ }, "lexical-scope": { "version": "1.1.0", - "from": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.1.0.tgz", + "from": "lexical-scope@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.1.0.tgz", "dependencies": { "astw": { "version": "1.1.0", - "from": "https://registry.npmjs.org/astw/-/astw-1.1.0.tgz", + "from": "astw@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/astw/-/astw-1.1.0.tgz", "dependencies": { "esprima-fb": { "version": "3001.1.0-dev-harmony-fb", - "from": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-3001.0001.0000-dev-harmony-fb.tgz", + "from": "esprima-fb@3001.1.0-dev-harmony-fb", "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-3001.0001.0000-dev-harmony-fb.tgz" } } @@ -920,51 +984,51 @@ }, "process": { "version": "0.6.0", - "from": "https://registry.npmjs.org/process/-/process-0.6.0.tgz", + "from": "process@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/process/-/process-0.6.0.tgz" }, "through": { "version": "2.3.6", - "from": "https://registry.npmjs.org/through/-/through-2.3.6.tgz", + "from": "through@>=2.3.4 <2.4.0", "resolved": "https://registry.npmjs.org/through/-/through-2.3.6.tgz" } } }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "labeled-stream-splicer": { "version": "1.0.2", - "from": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-1.0.2.tgz", + "from": "labeled-stream-splicer@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-1.0.2.tgz", "dependencies": { "stream-splicer": { "version": "1.3.1", - "from": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-1.3.1.tgz", + "from": "stream-splicer@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-1.3.1.tgz", "dependencies": { "readable-stream": { "version": "1.1.13", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "from": "readable-stream@>=1.1.13-1 <2.0.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" } } }, "readable-wrap": { "version": "1.0.0", - "from": "https://registry.npmjs.org/readable-wrap/-/readable-wrap-1.0.0.tgz", + "from": "readable-wrap@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/readable-wrap/-/readable-wrap-1.0.0.tgz" }, "indexof": { "version": "0.0.1", - "from": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "from": "indexof@0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz" } } @@ -972,102 +1036,102 @@ } }, "module-deps": { - "version": "3.7.2", - "from": "https://registry.npmjs.org/module-deps/-/module-deps-3.7.2.tgz", - "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-3.7.2.tgz", + "version": "3.7.5", + "from": "module-deps@>=3.6.3 <4.0.0", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-3.7.5.tgz", "dependencies": { "JSONStream": { "version": "0.7.4", - "from": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.7.4.tgz", + "from": "JSONStream@>=0.7.1 <0.8.0", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.7.4.tgz", "dependencies": { "jsonparse": { "version": "0.0.5", - "from": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "from": "jsonparse@0.0.5", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz" }, "through": { "version": "2.3.6", - "from": "https://registry.npmjs.org/through/-/through-2.3.6.tgz", + "from": "through@>=2.2.7 <3.0.0", "resolved": "https://registry.npmjs.org/through/-/through-2.3.6.tgz" } } }, "detective": { "version": "4.0.0", - "from": "https://registry.npmjs.org/detective/-/detective-4.0.0.tgz", + "from": "detective@>=4.0.0 <5.0.0", "resolved": "https://registry.npmjs.org/detective/-/detective-4.0.0.tgz", "dependencies": { "acorn": { "version": "0.9.0", - "from": "https://registry.npmjs.org/acorn/-/acorn-0.9.0.tgz", + "from": "acorn@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-0.9.0.tgz" }, "escodegen": { "version": "1.6.1", - "from": "https://registry.npmjs.org/escodegen/-/escodegen-1.6.1.tgz", + "from": "escodegen@>=1.4.1 <2.0.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.6.1.tgz", "dependencies": { "estraverse": { - "version": "1.9.1", - "from": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.1.tgz", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.1.tgz" + "version": "1.9.3", + "from": "estraverse@>=1.9.1 <2.0.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz" }, "esutils": { "version": "1.1.6", - "from": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz", + "from": "esutils@>=1.1.6 <2.0.0", "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz" }, "esprima": { - "version": "1.2.4", - "from": "https://registry.npmjs.org/esprima/-/esprima-1.2.4.tgz", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.4.tgz" + "version": "1.2.5", + "from": "esprima@>=1.2.2 <2.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz" }, "optionator": { "version": "0.5.0", - "from": "https://registry.npmjs.org/optionator/-/optionator-0.5.0.tgz", + "from": "optionator@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.5.0.tgz", "dependencies": { "prelude-ls": { "version": "1.1.1", - "from": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.1.tgz", + "from": "prelude-ls@>=1.1.1 <1.2.0", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.1.tgz" }, "deep-is": { "version": "0.1.3", - "from": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "from": "deep-is@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz" }, "wordwrap": { "version": "0.0.2", - "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "from": "wordwrap@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" }, "type-check": { "version": "0.3.1", - "from": "https://registry.npmjs.org/type-check/-/type-check-0.3.1.tgz", + "from": "type-check@>=0.3.1 <0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.1.tgz" }, "levn": { "version": "0.2.5", - "from": "https://registry.npmjs.org/levn/-/levn-0.2.5.tgz", + "from": "levn@>=0.2.5 <0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.2.5.tgz" }, "fast-levenshtein": { "version": "1.0.6", - "from": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.0.6.tgz", + "from": "fast-levenshtein@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.0.6.tgz" } } }, "source-map": { "version": "0.1.43", - "from": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "from": "source-map@>=0.1.40 <0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", + "from": "amdefine@>=0.0.4", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } @@ -1078,39 +1142,39 @@ }, "minimist": { "version": "0.2.0", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "from": "minimist@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz" }, "parents": { "version": "1.0.1", - "from": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "from": "parents@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", "dependencies": { "path-platform": { "version": "0.11.15", - "from": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "from": "path-platform@>=0.11.15 <0.12.0", "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz" } } }, "resolve": { - "version": "1.1.3", - "from": "https://registry.npmjs.org/resolve/-/resolve-1.1.3.tgz", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.3.tgz" + "version": "1.1.6", + "from": "resolve@>=1.1.3 <2.0.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.6.tgz" }, "stream-combiner2": { "version": "1.0.2", - "from": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.0.2.tgz", + "from": "stream-combiner2@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.0.2.tgz", "dependencies": { "through2": { "version": "0.5.1", - "from": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "from": "through2@>=0.5.1 <0.6.0", "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", "dependencies": { "xtend": { "version": "3.0.0", - "from": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "from": "xtend@>=3.0.0 <3.1.0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz" } } @@ -1119,29 +1183,29 @@ }, "subarg": { "version": "0.0.1", - "from": "https://registry.npmjs.org/subarg/-/subarg-0.0.1.tgz", + "from": "subarg@0.0.1", "resolved": "https://registry.npmjs.org/subarg/-/subarg-0.0.1.tgz", "dependencies": { "minimist": { "version": "0.0.10", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "from": "minimist@>=0.0.7 <0.1.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } }, "through2": { "version": "0.4.2", - "from": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "from": "through2@>=0.4.1 <0.5.0", "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", "dependencies": { "xtend": { "version": "2.1.2", - "from": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "from": "xtend@>=2.1.1 <2.2.0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", "dependencies": { "object-keys": { "version": "0.4.0", - "from": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "from": "object-keys@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz" } } @@ -1150,219 +1214,219 @@ }, "xtend": { "version": "4.0.0", - "from": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz", + "from": "xtend@>=4.0.0 <5.0.0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" } } }, "os-browserify": { "version": "0.1.2", - "from": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", + "from": "os-browserify@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz" }, "parents": { "version": "0.0.3", - "from": "https://registry.npmjs.org/parents/-/parents-0.0.3.tgz", + "from": "parents@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/parents/-/parents-0.0.3.tgz", "dependencies": { "path-platform": { "version": "0.0.1", - "from": "https://registry.npmjs.org/path-platform/-/path-platform-0.0.1.tgz", + "from": "path-platform@>=0.0.1 <0.0.2", "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.0.1.tgz" } } }, "path-browserify": { "version": "0.0.0", - "from": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "from": "path-browserify@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz" }, "process": { "version": "0.8.0", - "from": "https://registry.npmjs.org/process/-/process-0.8.0.tgz", + "from": "process@>=0.8.0 <0.9.0", "resolved": "https://registry.npmjs.org/process/-/process-0.8.0.tgz" }, "punycode": { "version": "1.2.4", - "from": "https://registry.npmjs.org/punycode/-/punycode-1.2.4.tgz", + "from": "punycode@>=1.2.3 <1.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.2.4.tgz" }, "querystring-es3": { "version": "0.2.1", - "from": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "from": "querystring-es3@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz" }, "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.33-1 <2.0.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" } } }, "resolve": { "version": "0.7.4", - "from": "https://registry.npmjs.org/resolve/-/resolve-0.7.4.tgz", + "from": "resolve@>=0.7.1 <0.8.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.7.4.tgz" }, "shallow-copy": { "version": "0.0.1", - "from": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", + "from": "shallow-copy@0.0.1", "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz" }, "shasum": { "version": "1.0.1", - "from": "https://registry.npmjs.org/shasum/-/shasum-1.0.1.tgz", + "from": "shasum@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.1.tgz", "dependencies": { "json-stable-stringify": { "version": "0.0.1", - "from": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "from": "json-stable-stringify@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", "dependencies": { "jsonify": { "version": "0.0.0", - "from": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "from": "jsonify@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" } } }, "sha.js": { "version": "2.3.6", - "from": "https://registry.npmjs.org/sha.js/-/sha.js-2.3.6.tgz", + "from": "sha.js@>=2.3.0 <2.4.0", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.3.6.tgz" } } }, "shell-quote": { "version": "0.0.1", - "from": "https://registry.npmjs.org/shell-quote/-/shell-quote-0.0.1.tgz", + "from": "shell-quote@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-0.0.1.tgz" }, "stream-browserify": { "version": "1.0.0", - "from": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-1.0.0.tgz", + "from": "stream-browserify@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-1.0.0.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "subarg": { "version": "1.0.0", - "from": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "from": "subarg@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz" }, "syntax-error": { "version": "1.1.2", - "from": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.1.2.tgz", + "from": "syntax-error@>=1.1.1 <2.0.0", "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.1.2.tgz", "dependencies": { "acorn": { "version": "0.9.0", - "from": "https://registry.npmjs.org/acorn/-/acorn-0.9.0.tgz", + "from": "acorn@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-0.9.0.tgz" } } }, "through2": { "version": "1.1.1", - "from": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", + "from": "through2@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", "dependencies": { "readable-stream": { "version": "1.1.13", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "from": "readable-stream@>=1.1.13-1 <1.2.0-0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" } } }, "xtend": { "version": "4.0.0", - "from": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz", + "from": "xtend@>=4.0.0 <4.1.0-0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" } } }, "timers-browserify": { - "version": "1.3.0", - "from": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.3.0.tgz", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.3.0.tgz", + "version": "1.4.0", + "from": "timers-browserify@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.0.tgz", "dependencies": { "process": { - "version": "0.10.0", - "from": "https://registry.npmjs.org/process/-/process-0.10.0.tgz", - "resolved": "https://registry.npmjs.org/process/-/process-0.10.0.tgz" + "version": "0.10.1", + "from": "process@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/process/-/process-0.10.1.tgz" } } }, "tty-browserify": { "version": "0.0.0", - "from": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "from": "tty-browserify@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz" }, "umd": { "version": "2.1.0", - "from": "https://registry.npmjs.org/umd/-/umd-2.1.0.tgz", + "from": "umd@>=2.1.0 <2.2.0", "resolved": "https://registry.npmjs.org/umd/-/umd-2.1.0.tgz", "dependencies": { "rfile": { "version": "1.0.0", - "from": "https://registry.npmjs.org/rfile/-/rfile-1.0.0.tgz", + "from": "rfile@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/rfile/-/rfile-1.0.0.tgz", "dependencies": { "callsite": { "version": "1.0.0", - "from": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "from": "callsite@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz" }, "resolve": { "version": "0.3.1", - "from": "https://registry.npmjs.org/resolve/-/resolve-0.3.1.tgz", + "from": "resolve@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.3.1.tgz" } } }, "ruglify": { "version": "1.0.0", - "from": "https://registry.npmjs.org/ruglify/-/ruglify-1.0.0.tgz", + "from": "ruglify@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/ruglify/-/ruglify-1.0.0.tgz", "dependencies": { "uglify-js": { "version": "2.2.5", - "from": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", + "from": "uglify-js@>=2.2.0 <2.3.0", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", "dependencies": { "source-map": { "version": "0.1.43", - "from": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "from": "source-map@>=0.1.7 <0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", + "from": "amdefine@>=0.0.4", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } }, "optimist": { "version": "0.3.7", - "from": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "from": "optimist@>=0.3.5 <0.4.0", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", "dependencies": { "wordwrap": { "version": "0.0.2", - "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "from": "wordwrap@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" } } @@ -1373,46 +1437,61 @@ }, "through": { "version": "2.3.6", - "from": "https://registry.npmjs.org/through/-/through-2.3.6.tgz", + "from": "through@>=2.3.4 <2.4.0", "resolved": "https://registry.npmjs.org/through/-/through-2.3.6.tgz" }, "uglify-js": { - "version": "2.4.16", - "from": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.16.tgz", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.16.tgz", + "version": "2.4.19", + "from": "uglify-js@>=2.4.0 <2.5.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.19.tgz", "dependencies": { "async": { "version": "0.2.10", - "from": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "from": "async@>=0.2.6 <0.3.0", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "source-map": { "version": "0.1.34", - "from": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz", + "from": "source-map@0.1.34", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", + "from": "amdefine@>=0.0.4", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } }, - "optimist": { - "version": "0.3.7", - "from": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "yargs": { + "version": "3.5.4", + "from": "yargs@>=3.5.4 <3.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz", "dependencies": { + "camelcase": { + "version": "1.0.2", + "from": "camelcase@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.0.2.tgz" + }, + "decamelize": { + "version": "1.0.0", + "from": "decamelize@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.0.0.tgz" + }, + "window-size": { + "version": "0.1.0", + "from": "window-size@0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz" + }, "wordwrap": { "version": "0.0.2", - "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "from": "wordwrap@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" } } }, "uglify-to-browserify": { "version": "1.0.2", - "from": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "from": "uglify-to-browserify@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz" } } @@ -1420,37 +1499,42 @@ } }, "url": { - "version": "0.10.2", - "from": "https://registry.npmjs.org/url/-/url-0.10.2.tgz", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.2.tgz", + "version": "0.10.3", + "from": "url@>=0.10.1 <0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", "dependencies": { "punycode": { "version": "1.3.2", - "from": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "from": "punycode@1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + }, + "querystring": { + "version": "0.2.0", + "from": "querystring@0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" } } }, "util": { "version": "0.10.3", - "from": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "from": "util@>=0.10.1 <0.11.0", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz" }, "vm-browserify": { "version": "0.0.4", - "from": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "from": "vm-browserify@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", "dependencies": { "indexof": { "version": "0.0.1", - "from": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "from": "indexof@0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz" } } }, "xtend": { "version": "3.0.0", - "from": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "from": "xtend@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz" } } @@ -1459,143 +1543,143 @@ }, "benchmark": { "version": "1.0.0", - "from": "https://registry.npmjs.org/benchmark/-/benchmark-1.0.0.tgz", + "from": "benchmark@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-1.0.0.tgz" }, "bower": { "version": "1.3.12", - "from": "https://registry.npmjs.org/bower/-/bower-1.3.12.tgz", + "from": "bower@>=1.3.9 <1.4.0", "resolved": "https://registry.npmjs.org/bower/-/bower-1.3.12.tgz", "dependencies": { "abbrev": { "version": "1.0.5", - "from": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz", + "from": "abbrev@>=1.0.4 <1.1.0", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz" }, "archy": { "version": "0.0.2", - "from": "https://registry.npmjs.org/archy/-/archy-0.0.2.tgz", + "from": "archy@0.0.2", "resolved": "https://registry.npmjs.org/archy/-/archy-0.0.2.tgz" }, "bower-config": { "version": "0.5.2", - "from": "https://registry.npmjs.org/bower-config/-/bower-config-0.5.2.tgz", + "from": "bower-config@>=0.5.2 <0.6.0", "resolved": "https://registry.npmjs.org/bower-config/-/bower-config-0.5.2.tgz", "dependencies": { "graceful-fs": { "version": "2.0.3", - "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "from": "graceful-fs@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz" }, "optimist": { "version": "0.6.1", - "from": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "from": "optimist@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "dependencies": { "wordwrap": { "version": "0.0.2", - "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "from": "wordwrap@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" }, "minimist": { "version": "0.0.10", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "from": "minimist@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } }, "osenv": { "version": "0.0.3", - "from": "https://registry.npmjs.org/osenv/-/osenv-0.0.3.tgz", + "from": "osenv@0.0.3", "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.0.3.tgz" } } }, "bower-endpoint-parser": { "version": "0.2.2", - "from": "https://registry.npmjs.org/bower-endpoint-parser/-/bower-endpoint-parser-0.2.2.tgz", + "from": "bower-endpoint-parser@>=0.2.2 <0.3.0", "resolved": "https://registry.npmjs.org/bower-endpoint-parser/-/bower-endpoint-parser-0.2.2.tgz" }, "bower-json": { "version": "0.4.0", - "from": "https://registry.npmjs.org/bower-json/-/bower-json-0.4.0.tgz", + "from": "bower-json@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/bower-json/-/bower-json-0.4.0.tgz", "dependencies": { "deep-extend": { "version": "0.2.11", - "from": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.2.11.tgz", + "from": "deep-extend@>=0.2.5 <0.3.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.2.11.tgz" }, "graceful-fs": { "version": "2.0.3", - "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "from": "graceful-fs@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz" }, "intersect": { "version": "0.0.3", - "from": "https://registry.npmjs.org/intersect/-/intersect-0.0.3.tgz", + "from": "intersect@>=0.0.3 <0.1.0", "resolved": "https://registry.npmjs.org/intersect/-/intersect-0.0.3.tgz" } } }, "bower-logger": { "version": "0.2.2", - "from": "https://registry.npmjs.org/bower-logger/-/bower-logger-0.2.2.tgz", + "from": "bower-logger@>=0.2.2 <0.3.0", "resolved": "https://registry.npmjs.org/bower-logger/-/bower-logger-0.2.2.tgz" }, "bower-registry-client": { - "version": "0.2.3", - "from": "https://registry.npmjs.org/bower-registry-client/-/bower-registry-client-0.2.3.tgz", - "resolved": "https://registry.npmjs.org/bower-registry-client/-/bower-registry-client-0.2.3.tgz", + "version": "0.2.4", + "from": "bower-registry-client@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/bower-registry-client/-/bower-registry-client-0.2.4.tgz", "dependencies": { "async": { "version": "0.2.10", - "from": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "from": "async@>=0.2.8 <0.3.0", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "graceful-fs": { "version": "2.0.3", - "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "from": "graceful-fs@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz" }, "lru-cache": { "version": "2.3.1", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.3.1.tgz", + "from": "lru-cache@>=2.3.0 <2.4.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.3.1.tgz" }, "request": { "version": "2.51.0", - "from": "https://registry.npmjs.org/request/-/request-2.51.0.tgz", + "from": "request@>=2.51.0 <2.52.0", "resolved": "https://registry.npmjs.org/request/-/request-2.51.0.tgz", "dependencies": { "bl": { "version": "0.9.4", - "from": "https://registry.npmjs.org/bl/-/bl-0.9.4.tgz", + "from": "bl@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.4.tgz", "dependencies": { "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.26 <1.1.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } @@ -1604,33 +1688,33 @@ }, "caseless": { "version": "0.8.0", - "from": "https://registry.npmjs.org/caseless/-/caseless-0.8.0.tgz", + "from": "caseless@>=0.8.0 <0.9.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.8.0.tgz" }, "forever-agent": { "version": "0.5.2", - "from": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "from": "forever-agent@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" }, "form-data": { "version": "0.2.0", - "from": "https://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz", + "from": "form-data@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz", "dependencies": { "async": { "version": "0.9.0", - "from": "https://registry.npmjs.org/async/-/async-0.9.0.tgz", + "from": "async@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" }, "mime-types": { - "version": "2.0.9", - "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", + "version": "2.0.10", + "from": "mime-types@>=2.0.3 <2.1.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.10.tgz", "dependencies": { "mime-db": { - "version": "1.7.0", - "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz" + "version": "1.8.0", + "from": "mime-db@>=1.8.0 <1.9.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.8.0.tgz" } } } @@ -1638,113 +1722,113 @@ }, "json-stringify-safe": { "version": "5.0.0", - "from": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz", + "from": "json-stringify-safe@>=5.0.0 <5.1.0", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" }, "mime-types": { "version": "1.0.2", - "from": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "from": "mime-types@>=1.0.1 <1.1.0", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz" }, "node-uuid": { - "version": "1.4.2", - "from": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz" + "version": "1.4.3", + "from": "node-uuid@>=1.4.0 <1.5.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" }, "qs": { "version": "2.3.3", - "from": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "from": "qs@>=2.3.1 <2.4.0", "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz" }, "tunnel-agent": { "version": "0.4.0", - "from": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz", + "from": "tunnel-agent@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz" }, "tough-cookie": { "version": "0.12.1", - "from": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", + "from": "tough-cookie@>=0.12.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", "dependencies": { "punycode": { "version": "1.3.2", - "from": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "from": "punycode@>=0.2.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" } } }, "http-signature": { "version": "0.10.1", - "from": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "from": "http-signature@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", "dependencies": { "assert-plus": { "version": "0.1.5", - "from": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "from": "assert-plus@>=0.1.5 <0.2.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" }, "asn1": { "version": "0.1.11", - "from": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "from": "asn1@0.1.11", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" }, "ctype": { "version": "0.5.3", - "from": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "from": "ctype@0.5.3", "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" } } }, "oauth-sign": { "version": "0.5.0", - "from": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz", + "from": "oauth-sign@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz" }, "hawk": { "version": "1.1.1", - "from": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "from": "hawk@1.1.1", "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", "dependencies": { "hoek": { "version": "0.9.1", - "from": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "from": "hoek@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" }, "boom": { "version": "0.4.2", - "from": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "from": "boom@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" }, "cryptiles": { "version": "0.2.2", - "from": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "from": "cryptiles@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" }, "sntp": { "version": "0.2.4", - "from": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "from": "sntp@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" } } }, "aws-sign2": { "version": "0.5.0", - "from": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "from": "aws-sign2@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" }, "stringstream": { "version": "0.0.4", - "from": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz", + "from": "stringstream@>=0.0.4 <0.1.0", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz" }, "combined-stream": { "version": "0.0.7", - "from": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "from": "combined-stream@>=0.0.5 <0.1.0", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", "dependencies": { "delayed-stream": { "version": "0.0.5", - "from": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "from": "delayed-stream@0.0.5", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" } } @@ -1753,29 +1837,29 @@ }, "request-replay": { "version": "0.2.0", - "from": "https://registry.npmjs.org/request-replay/-/request-replay-0.2.0.tgz", + "from": "request-replay@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/request-replay/-/request-replay-0.2.0.tgz" }, "mkdirp": { "version": "0.3.5", - "from": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "from": "mkdirp@>=0.3.5 <0.4.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" } } }, "cardinal": { "version": "0.4.0", - "from": "https://registry.npmjs.org/cardinal/-/cardinal-0.4.0.tgz", + "from": "cardinal@0.4.0", "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-0.4.0.tgz", "dependencies": { "redeyed": { "version": "0.4.4", - "from": "https://registry.npmjs.org/redeyed/-/redeyed-0.4.4.tgz", + "from": "redeyed@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-0.4.4.tgz", "dependencies": { "esprima": { "version": "1.0.4", - "from": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "from": "esprima@>=1.0.4 <1.1.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz" } } @@ -1784,175 +1868,175 @@ }, "chalk": { "version": "0.5.0", - "from": "https://registry.npmjs.org/chalk/-/chalk-0.5.0.tgz", + "from": "chalk@0.5.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.0.tgz", "dependencies": { "ansi-styles": { "version": "1.1.0", - "from": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "from": "ansi-styles@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" }, "escape-string-regexp": { - "version": "1.0.2", - "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz" + "version": "1.0.3", + "from": "escape-string-regexp@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz" }, "has-ansi": { "version": "0.1.0", - "from": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "from": "has-ansi@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "from": "ansi-regex@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "strip-ansi": { "version": "0.3.0", - "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "from": "strip-ansi@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "from": "ansi-regex@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "supports-color": { "version": "0.2.0", - "from": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "from": "supports-color@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" } } }, "chmodr": { "version": "0.1.0", - "from": "https://registry.npmjs.org/chmodr/-/chmodr-0.1.0.tgz", + "from": "chmodr@0.1.0", "resolved": "https://registry.npmjs.org/chmodr/-/chmodr-0.1.0.tgz" }, "decompress-zip": { "version": "0.0.8", - "from": "https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.0.8.tgz", + "from": "decompress-zip@0.0.8", "resolved": "https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.0.8.tgz", "dependencies": { "mkpath": { "version": "0.1.0", - "from": "https://registry.npmjs.org/mkpath/-/mkpath-0.1.0.tgz", + "from": "mkpath@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-0.1.0.tgz" }, "binary": { "version": "0.3.0", - "from": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "from": "binary@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", "dependencies": { "chainsaw": { "version": "0.1.0", - "from": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "from": "chainsaw@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "dependencies": { "traverse": { "version": "0.3.9", - "from": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "from": "traverse@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz" } } }, "buffers": { "version": "0.1.1", - "from": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "from": "buffers@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz" } } }, "touch": { "version": "0.0.2", - "from": "https://registry.npmjs.org/touch/-/touch-0.0.2.tgz", + "from": "touch@0.0.2", "resolved": "https://registry.npmjs.org/touch/-/touch-0.0.2.tgz", "dependencies": { "nopt": { "version": "1.0.10", - "from": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "from": "nopt@>=1.0.10 <1.1.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz" } } }, "readable-stream": { "version": "1.1.13", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "from": "readable-stream@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "nopt": { "version": "2.2.1", - "from": "https://registry.npmjs.org/nopt/-/nopt-2.2.1.tgz", + "from": "nopt@>=2.2.0 <2.3.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.2.1.tgz" } } }, "fstream": { "version": "1.0.4", - "from": "https://registry.npmjs.org/fstream/-/fstream-1.0.4.tgz", + "from": "fstream@>=1.0.2 <1.1.0", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.4.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "fstream-ignore": { "version": "1.0.2", - "from": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.2.tgz", + "from": "fstream-ignore@>=1.0.1 <1.1.0", "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.2.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { - "version": "2.0.1", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.1.tgz", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.1.tgz", + "version": "2.0.4", + "from": "minimatch@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.4.tgz", "dependencies": { "brace-expansion": { "version": "1.1.0", - "from": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", + "from": "brace-expansion@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", "dependencies": { "balanced-match": { "version": "0.2.0", - "from": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz", + "from": "balanced-match@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz" }, "concat-map": { "version": "0.0.1", - "from": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "from": "concat-map@0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" } } @@ -1963,34 +2047,34 @@ }, "glob": { "version": "4.0.6", - "from": "https://registry.npmjs.org/glob/-/glob-4.0.6.tgz", + "from": "glob@>=4.0.6 <4.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-4.0.6.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "1.0.0", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", + "from": "minimatch@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", "dependencies": { "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "once": { "version": "1.3.1", - "from": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "from": "once@>=1.3.0 <2.0.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -1998,45 +2082,45 @@ } }, "graceful-fs": { - "version": "3.0.5", - "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz" + "version": "3.0.6", + "from": "graceful-fs@>=3.0.1 <3.1.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.6.tgz" }, "handlebars": { "version": "2.0.0", - "from": "https://registry.npmjs.org/handlebars/-/handlebars-2.0.0.tgz", + "from": "handlebars@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-2.0.0.tgz", "dependencies": { "optimist": { "version": "0.3.7", - "from": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "from": "optimist@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", "dependencies": { "wordwrap": { "version": "0.0.2", - "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "from": "wordwrap@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" } } }, "uglify-js": { "version": "2.3.6", - "from": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.3.6.tgz", + "from": "uglify-js@>=2.3.0 <2.4.0", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.3.6.tgz", "dependencies": { "async": { "version": "0.2.10", - "from": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "from": "async@>=0.2.6 <0.3.0", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "source-map": { "version": "0.1.43", - "from": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "from": "source-map@>=0.1.7 <0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", + "from": "amdefine@>=0.0.4", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } @@ -2047,90 +2131,90 @@ }, "inquirer": { "version": "0.7.1", - "from": "https://registry.npmjs.org/inquirer/-/inquirer-0.7.1.tgz", + "from": "inquirer@0.7.1", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.7.1.tgz", "dependencies": { "cli-color": { - "version": "0.3.2", - "from": "https://registry.npmjs.org/cli-color/-/cli-color-0.3.2.tgz", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.3.2.tgz", + "version": "0.3.3", + "from": "cli-color@>=0.3.2 <0.4.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.3.3.tgz", "dependencies": { "d": { "version": "0.1.1", - "from": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "from": "d@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz" }, "es5-ext": { "version": "0.10.6", - "from": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.6.tgz", + "from": "es5-ext@>=0.10.6 <0.11.0", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.6.tgz", "dependencies": { "es6-iterator": { "version": "0.1.3", - "from": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", + "from": "es6-iterator@>=0.1.3 <0.2.0", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz" }, "es6-symbol": { "version": "2.0.1", - "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", + "from": "es6-symbol@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz" } } }, "memoizee": { "version": "0.3.8", - "from": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.8.tgz", + "from": "memoizee@>=0.3.8 <0.4.0", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.8.tgz", "dependencies": { "es6-weak-map": { "version": "0.1.2", - "from": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.2.tgz", + "from": "es6-weak-map@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.2.tgz", "dependencies": { "es6-iterator": { "version": "0.1.3", - "from": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", + "from": "es6-iterator@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", "dependencies": { "es6-symbol": { "version": "2.0.1", - "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", + "from": "es6-symbol@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz" } } }, "es6-symbol": { "version": "0.1.1", - "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-0.1.1.tgz", + "from": "es6-symbol@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-0.1.1.tgz" } } }, "event-emitter": { "version": "0.3.3", - "from": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.3.tgz", + "from": "event-emitter@>=0.3.1 <0.4.0", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.3.tgz" }, "lru-queue": { "version": "0.1.0", - "from": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "from": "lru-queue@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz" }, "next-tick": { "version": "0.2.2", - "from": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", + "from": "next-tick@>=0.2.2 <0.3.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz" } } }, "timers-ext": { "version": "0.1.0", - "from": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.0.tgz", + "from": "timers-ext@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.0.tgz", "dependencies": { "next-tick": { "version": "0.2.2", - "from": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", + "from": "next-tick@>=0.2.2 <0.3.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz" } } @@ -2139,243 +2223,243 @@ }, "figures": { "version": "1.3.5", - "from": "https://registry.npmjs.org/figures/-/figures-1.3.5.tgz", + "from": "figures@>=1.3.2 <2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.3.5.tgz" }, "mute-stream": { "version": "0.0.4", - "from": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", + "from": "mute-stream@0.0.4", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz" }, "readline2": { "version": "0.1.1", - "from": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", + "from": "readline2@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", "dependencies": { "strip-ansi": { "version": "2.0.1", - "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", + "from": "strip-ansi@>=2.0.1 <3.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", "dependencies": { "ansi-regex": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.0.tgz" + "version": "1.1.1", + "from": "ansi-regex@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz" } } } } }, "rx": { - "version": "2.4.0", - "from": "https://registry.npmjs.org/rx/-/rx-2.4.0.tgz", - "resolved": "https://registry.npmjs.org/rx/-/rx-2.4.0.tgz" + "version": "2.4.9", + "from": "rx@>=2.2.27 <3.0.0", + "resolved": "https://registry.npmjs.org/rx/-/rx-2.4.9.tgz" }, "through": { "version": "2.3.6", - "from": "https://registry.npmjs.org/through/-/through-2.3.6.tgz", + "from": "through@>=2.3.4 <2.4.0", "resolved": "https://registry.npmjs.org/through/-/through-2.3.6.tgz" } } }, "insight": { "version": "0.4.3", - "from": "https://registry.npmjs.org/insight/-/insight-0.4.3.tgz", + "from": "insight@0.4.3", "resolved": "https://registry.npmjs.org/insight/-/insight-0.4.3.tgz", "dependencies": { "async": { "version": "0.9.0", - "from": "https://registry.npmjs.org/async/-/async-0.9.0.tgz", + "from": "async@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" }, "chalk": { "version": "0.5.1", - "from": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "from": "chalk@>=0.5.1 <0.6.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "dependencies": { "ansi-styles": { "version": "1.1.0", - "from": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "from": "ansi-styles@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" }, "escape-string-regexp": { - "version": "1.0.2", - "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz" + "version": "1.0.3", + "from": "escape-string-regexp@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz" }, "has-ansi": { "version": "0.1.0", - "from": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "from": "has-ansi@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "from": "ansi-regex@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "strip-ansi": { "version": "0.3.0", - "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "from": "strip-ansi@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "from": "ansi-regex@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "supports-color": { "version": "0.2.0", - "from": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "from": "supports-color@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" } } }, "configstore": { "version": "0.3.2", - "from": "https://registry.npmjs.org/configstore/-/configstore-0.3.2.tgz", + "from": "configstore@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/configstore/-/configstore-0.3.2.tgz", "dependencies": { "js-yaml": { "version": "3.2.7", - "from": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.2.7.tgz", + "from": "js-yaml@>=3.1.0 <4.0.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.2.7.tgz", "dependencies": { "argparse": { - "version": "1.0.1", - "from": "https://registry.npmjs.org/argparse/-/argparse-1.0.1.tgz", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.1.tgz", + "version": "1.0.2", + "from": "argparse@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.2.tgz", "dependencies": { "lodash": { - "version": "3.2.0", - "from": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz" + "version": "3.6.0", + "from": "lodash@>=3.2.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.6.0.tgz" }, "sprintf-js": { "version": "1.0.2", - "from": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.2.tgz", + "from": "sprintf-js@>=1.0.2 <1.1.0", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.2.tgz" } } }, "esprima": { "version": "2.0.0", - "from": "https://registry.npmjs.org/esprima/-/esprima-2.0.0.tgz", + "from": "esprima@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.0.0.tgz" } } }, "object-assign": { "version": "2.0.0", - "from": "https://registry.npmjs.org/object-assign/-/object-assign-2.0.0.tgz", + "from": "object-assign@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.0.0.tgz" }, "user-home": { "version": "1.1.1", - "from": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "from": "user-home@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz" }, "uuid": { "version": "2.0.1", - "from": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "from": "uuid@>=2.0.1 <3.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz" }, "xdg-basedir": { "version": "1.0.1", - "from": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-1.0.1.tgz", + "from": "xdg-basedir@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-1.0.1.tgz" } } }, "inquirer": { "version": "0.6.0", - "from": "https://registry.npmjs.org/inquirer/-/inquirer-0.6.0.tgz", + "from": "inquirer@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.6.0.tgz", "dependencies": { "cli-color": { - "version": "0.3.2", - "from": "https://registry.npmjs.org/cli-color/-/cli-color-0.3.2.tgz", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.3.2.tgz", + "version": "0.3.3", + "from": "cli-color@>=0.3.2 <0.4.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.3.3.tgz", "dependencies": { "d": { "version": "0.1.1", - "from": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "from": "d@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz" }, "es5-ext": { "version": "0.10.6", - "from": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.6.tgz", + "from": "es5-ext@>=0.10.6 <0.11.0", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.6.tgz", "dependencies": { "es6-iterator": { "version": "0.1.3", - "from": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", + "from": "es6-iterator@>=0.1.3 <0.2.0", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz" }, "es6-symbol": { "version": "2.0.1", - "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", + "from": "es6-symbol@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz" } } }, "memoizee": { "version": "0.3.8", - "from": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.8.tgz", + "from": "memoizee@>=0.3.8 <0.4.0", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.8.tgz", "dependencies": { "es6-weak-map": { "version": "0.1.2", - "from": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.2.tgz", + "from": "es6-weak-map@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.2.tgz", "dependencies": { "es6-iterator": { "version": "0.1.3", - "from": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", + "from": "es6-iterator@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", "dependencies": { "es6-symbol": { "version": "2.0.1", - "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", + "from": "es6-symbol@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz" } } }, "es6-symbol": { "version": "0.1.1", - "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-0.1.1.tgz", + "from": "es6-symbol@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-0.1.1.tgz" } } }, "event-emitter": { "version": "0.3.3", - "from": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.3.tgz", + "from": "event-emitter@>=0.3.1 <0.4.0", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.3.tgz" }, "lru-queue": { "version": "0.1.0", - "from": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "from": "lru-queue@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz" }, "next-tick": { "version": "0.2.2", - "from": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", + "from": "next-tick@>=0.2.2 <0.3.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz" } } }, "timers-ext": { "version": "0.1.0", - "from": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.0.tgz", + "from": "timers-ext@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.0.tgz", "dependencies": { "next-tick": { "version": "0.2.2", - "from": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", + "from": "next-tick@>=0.2.2 <0.3.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz" } } @@ -2384,70 +2468,70 @@ }, "mute-stream": { "version": "0.0.4", - "from": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", + "from": "mute-stream@0.0.4", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz" }, "readline2": { "version": "0.1.1", - "from": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", + "from": "readline2@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", "dependencies": { "strip-ansi": { "version": "2.0.1", - "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", + "from": "strip-ansi@>=2.0.1 <3.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", "dependencies": { "ansi-regex": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.0.tgz" + "version": "1.1.1", + "from": "ansi-regex@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz" } } } } }, "rx": { - "version": "2.4.0", - "from": "https://registry.npmjs.org/rx/-/rx-2.4.0.tgz", - "resolved": "https://registry.npmjs.org/rx/-/rx-2.4.0.tgz" + "version": "2.4.9", + "from": "rx@>=2.2.27 <3.0.0", + "resolved": "https://registry.npmjs.org/rx/-/rx-2.4.9.tgz" }, "through": { "version": "2.3.6", - "from": "https://registry.npmjs.org/through/-/through-2.3.6.tgz", + "from": "through@>=2.3.4 <2.4.0", "resolved": "https://registry.npmjs.org/through/-/through-2.3.6.tgz" } } }, "lodash.debounce": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-2.4.1.tgz", + "from": "lodash.debounce@>=2.4.1 <3.0.0", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-2.4.1.tgz", "dependencies": { "lodash.isfunction": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-2.4.1.tgz", + "from": "lodash.isfunction@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-2.4.1.tgz" }, "lodash.isobject": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "from": "lodash.isobject@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } }, "lodash.now": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.now/-/lodash.now-2.4.1.tgz", + "from": "lodash.now@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.now/-/lodash.now-2.4.1.tgz", "dependencies": { "lodash._isnative": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "from": "lodash._isnative@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" } } @@ -2456,41 +2540,41 @@ }, "object-assign": { "version": "1.0.0", - "from": "https://registry.npmjs.org/object-assign/-/object-assign-1.0.0.tgz", + "from": "object-assign@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-1.0.0.tgz" }, "os-name": { "version": "1.0.3", - "from": "https://registry.npmjs.org/os-name/-/os-name-1.0.3.tgz", + "from": "os-name@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/os-name/-/os-name-1.0.3.tgz", "dependencies": { "osx-release": { "version": "1.0.0", - "from": "https://registry.npmjs.org/osx-release/-/osx-release-1.0.0.tgz", + "from": "osx-release@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/osx-release/-/osx-release-1.0.0.tgz", "dependencies": { "minimist": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/minimist/-/minimist-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.0.tgz" + "version": "1.1.1", + "from": "minimist@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.1.tgz" } } }, "win-release": { "version": "1.0.0", - "from": "https://registry.npmjs.org/win-release/-/win-release-1.0.0.tgz", + "from": "win-release@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/win-release/-/win-release-1.0.0.tgz" } } }, "tough-cookie": { "version": "0.12.1", - "from": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", + "from": "tough-cookie@>=0.12.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", "dependencies": { "punycode": { "version": "1.3.2", - "from": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "from": "punycode@>=0.2.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" } } @@ -2499,81 +2583,81 @@ }, "is-root": { "version": "1.0.0", - "from": "https://registry.npmjs.org/is-root/-/is-root-1.0.0.tgz", + "from": "is-root@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/is-root/-/is-root-1.0.0.tgz" }, "junk": { - "version": "1.0.0", - "from": "https://registry.npmjs.org/junk/-/junk-1.0.0.tgz", - "resolved": "https://registry.npmjs.org/junk/-/junk-1.0.0.tgz" + "version": "1.0.1", + "from": "junk@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/junk/-/junk-1.0.1.tgz" }, "lockfile": { "version": "1.0.0", - "from": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.0.tgz", + "from": "lockfile@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.0.tgz" }, "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "mkdirp": { "version": "0.5.0", - "from": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "from": "mkdirp@>=0.0.0 <1.0.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "from": "minimist@0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "mout": { "version": "0.9.1", - "from": "https://registry.npmjs.org/mout/-/mout-0.9.1.tgz", + "from": "mout@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/mout/-/mout-0.9.1.tgz" }, "nopt": { "version": "3.0.1", - "from": "https://registry.npmjs.org/nopt/-/nopt-3.0.1.tgz", + "from": "nopt@>=3.0.0 <3.1.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.1.tgz" }, "opn": { "version": "1.0.1", - "from": "https://registry.npmjs.org/opn/-/opn-1.0.1.tgz", + "from": "opn@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/opn/-/opn-1.0.1.tgz" }, "osenv": { "version": "0.1.0", - "from": "https://registry.npmjs.org/osenv/-/osenv-0.1.0.tgz", + "from": "osenv@0.1.0", "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.0.tgz" }, "p-throttler": { "version": "0.1.0", - "from": "https://registry.npmjs.org/p-throttler/-/p-throttler-0.1.0.tgz", + "from": "p-throttler@0.1.0", "resolved": "https://registry.npmjs.org/p-throttler/-/p-throttler-0.1.0.tgz", "dependencies": { "q": { "version": "0.9.7", - "from": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "from": "q@>=0.9.2 <0.10.0", "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz" } } }, "promptly": { "version": "0.2.0", - "from": "https://registry.npmjs.org/promptly/-/promptly-0.2.0.tgz", + "from": "promptly@0.2.0", "resolved": "https://registry.npmjs.org/promptly/-/promptly-0.2.0.tgz", "dependencies": { "read": { "version": "1.0.5", - "from": "https://registry.npmjs.org/read/-/read-1.0.5.tgz", + "from": "read@>=1.0.4 <1.1.0", "resolved": "https://registry.npmjs.org/read/-/read-1.0.5.tgz", "dependencies": { "mute-stream": { "version": "0.0.4", - "from": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", + "from": "mute-stream@>=0.0.4 <0.1.0", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz" } } @@ -2582,37 +2666,37 @@ }, "request": { "version": "2.42.0", - "from": "https://registry.npmjs.org/request/-/request-2.42.0.tgz", + "from": "request@>=2.42.0 <2.43.0", "resolved": "https://registry.npmjs.org/request/-/request-2.42.0.tgz", "dependencies": { "bl": { "version": "0.9.4", - "from": "https://registry.npmjs.org/bl/-/bl-0.9.4.tgz", + "from": "bl@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.4.tgz", "dependencies": { "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.26 <1.1.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } @@ -2621,233 +2705,233 @@ }, "caseless": { "version": "0.6.0", - "from": "https://registry.npmjs.org/caseless/-/caseless-0.6.0.tgz", + "from": "caseless@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.6.0.tgz" }, "forever-agent": { "version": "0.5.2", - "from": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "from": "forever-agent@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" }, "qs": { "version": "1.2.2", - "from": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz", + "from": "qs@>=1.2.0 <1.3.0", "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz" }, "json-stringify-safe": { "version": "5.0.0", - "from": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz", + "from": "json-stringify-safe@>=5.0.0 <5.1.0", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" }, "mime-types": { "version": "1.0.2", - "from": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "from": "mime-types@>=1.0.1 <1.1.0", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz" }, "node-uuid": { - "version": "1.4.2", - "from": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz" + "version": "1.4.3", + "from": "node-uuid@>=1.4.2 <2.0.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" }, "tunnel-agent": { "version": "0.4.0", - "from": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz", + "from": "tunnel-agent@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz" }, "tough-cookie": { "version": "0.12.1", - "from": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", + "from": "tough-cookie@>=0.12.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", "dependencies": { "punycode": { "version": "1.3.2", - "from": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "from": "punycode@>=0.2.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" } } }, "form-data": { "version": "0.1.4", - "from": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "from": "form-data@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", "dependencies": { "combined-stream": { "version": "0.0.7", - "from": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "from": "combined-stream@>=0.0.5 <0.1.0", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", "dependencies": { "delayed-stream": { "version": "0.0.5", - "from": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "from": "delayed-stream@0.0.5", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" } } }, "mime": { "version": "1.2.11", - "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "from": "mime@>=1.2.11 <1.3.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "async": { "version": "0.9.0", - "from": "https://registry.npmjs.org/async/-/async-0.9.0.tgz", + "from": "async@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" } } }, "http-signature": { "version": "0.10.1", - "from": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "from": "http-signature@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", "dependencies": { "assert-plus": { "version": "0.1.5", - "from": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "from": "assert-plus@>=0.1.5 <0.2.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" }, "asn1": { "version": "0.1.11", - "from": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "from": "asn1@0.1.11", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" }, "ctype": { "version": "0.5.3", - "from": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "from": "ctype@0.5.3", "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" } } }, "oauth-sign": { "version": "0.4.0", - "from": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.4.0.tgz", + "from": "oauth-sign@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.4.0.tgz" }, "hawk": { "version": "1.1.1", - "from": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "from": "hawk@1.1.1", "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", "dependencies": { "hoek": { "version": "0.9.1", - "from": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "from": "hoek@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" }, "boom": { "version": "0.4.2", - "from": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "from": "boom@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" }, "cryptiles": { "version": "0.2.2", - "from": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "from": "cryptiles@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" }, "sntp": { "version": "0.2.4", - "from": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "from": "sntp@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" } } }, "aws-sign2": { "version": "0.5.0", - "from": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "from": "aws-sign2@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" }, "stringstream": { "version": "0.0.4", - "from": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz", + "from": "stringstream@>=0.0.4 <0.1.0", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz" } } }, "request-progress": { "version": "0.3.0", - "from": "https://registry.npmjs.org/request-progress/-/request-progress-0.3.0.tgz", + "from": "request-progress@0.3.0", "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-0.3.0.tgz", "dependencies": { "throttleit": { "version": "0.0.2", - "from": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", + "from": "throttleit@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz" } } }, "retry": { "version": "0.6.0", - "from": "https://registry.npmjs.org/retry/-/retry-0.6.0.tgz", + "from": "retry@0.6.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.6.0.tgz" }, "rimraf": { "version": "2.2.8", - "from": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "from": "rimraf@>=2.2.0 <2.3.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" }, "semver": { "version": "2.3.2", - "from": "https://registry.npmjs.org/semver/-/semver-2.3.2.tgz", + "from": "semver@>=2.3.0 <2.4.0", "resolved": "https://registry.npmjs.org/semver/-/semver-2.3.2.tgz" }, "shell-quote": { - "version": "1.4.2", - "from": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.4.2.tgz", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.4.2.tgz", + "version": "1.4.3", + "from": "shell-quote@>=1.4.1 <1.5.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.4.3.tgz", "dependencies": { "jsonify": { "version": "0.0.0", - "from": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "from": "jsonify@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" }, "array-filter": { "version": "0.0.1", - "from": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "from": "array-filter@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz" }, "array-reduce": { "version": "0.0.0", - "from": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "from": "array-reduce@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz" }, "array-map": { "version": "0.0.0", - "from": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "from": "array-map@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz" } } }, "stringify-object": { - "version": "1.0.0", - "from": "https://registry.npmjs.org/stringify-object/-/stringify-object-1.0.0.tgz", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-1.0.0.tgz" + "version": "1.0.1", + "from": "stringify-object@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-1.0.1.tgz" }, "tar-fs": { "version": "0.5.2", - "from": "https://registry.npmjs.org/tar-fs/-/tar-fs-0.5.2.tgz", + "from": "tar-fs@0.5.2", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-0.5.2.tgz", "dependencies": { "pump": { "version": "0.3.5", - "from": "https://registry.npmjs.org/pump/-/pump-0.3.5.tgz", + "from": "pump@>=0.3.5 <0.4.0", "resolved": "https://registry.npmjs.org/pump/-/pump-0.3.5.tgz", "dependencies": { "once": { "version": "1.2.0", - "from": "https://registry.npmjs.org/once/-/once-1.2.0.tgz", + "from": "once@>=1.2.0 <1.3.0", "resolved": "https://registry.npmjs.org/once/-/once-1.2.0.tgz" }, "end-of-stream": { "version": "1.0.0", - "from": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", + "from": "end-of-stream@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", "dependencies": { "once": { "version": "1.3.1", - "from": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "from": "once@>=1.3.0 <1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -2858,27 +2942,27 @@ }, "tar-stream": { "version": "0.4.7", - "from": "https://registry.npmjs.org/tar-stream/-/tar-stream-0.4.7.tgz", + "from": "tar-stream@>=0.4.6 <0.5.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-0.4.7.tgz", "dependencies": { "bl": { "version": "0.9.4", - "from": "https://registry.npmjs.org/bl/-/bl-0.9.4.tgz", + "from": "bl@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.4.tgz" }, "end-of-stream": { "version": "1.1.0", - "from": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.1.0.tgz", + "from": "end-of-stream@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.1.0.tgz", "dependencies": { "once": { "version": "1.3.1", - "from": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "from": "once@>=1.3.0 <1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -2887,34 +2971,34 @@ }, "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.27-1 <2.0.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "xtend": { "version": "4.0.0", - "from": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz", + "from": "xtend@>=4.0.0 <5.0.0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" } } @@ -2923,139 +3007,139 @@ }, "tmp": { "version": "0.0.23", - "from": "https://registry.npmjs.org/tmp/-/tmp-0.0.23.tgz", + "from": "tmp@0.0.23", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.23.tgz" }, "update-notifier": { "version": "0.2.0", - "from": "https://registry.npmjs.org/update-notifier/-/update-notifier-0.2.0.tgz", + "from": "update-notifier@0.2.0", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-0.2.0.tgz", "dependencies": { "configstore": { "version": "0.3.2", - "from": "https://registry.npmjs.org/configstore/-/configstore-0.3.2.tgz", + "from": "configstore@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/configstore/-/configstore-0.3.2.tgz", "dependencies": { "js-yaml": { "version": "3.2.7", - "from": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.2.7.tgz", + "from": "js-yaml@>=3.1.0 <4.0.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.2.7.tgz", "dependencies": { "argparse": { - "version": "1.0.1", - "from": "https://registry.npmjs.org/argparse/-/argparse-1.0.1.tgz", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.1.tgz", + "version": "1.0.2", + "from": "argparse@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.2.tgz", "dependencies": { "lodash": { - "version": "3.2.0", - "from": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.2.0.tgz" + "version": "3.6.0", + "from": "lodash@>=3.2.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.6.0.tgz" }, "sprintf-js": { "version": "1.0.2", - "from": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.2.tgz", + "from": "sprintf-js@>=1.0.2 <1.1.0", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.2.tgz" } } }, "esprima": { "version": "2.0.0", - "from": "https://registry.npmjs.org/esprima/-/esprima-2.0.0.tgz", + "from": "esprima@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.0.0.tgz" } } }, "object-assign": { "version": "2.0.0", - "from": "https://registry.npmjs.org/object-assign/-/object-assign-2.0.0.tgz", + "from": "object-assign@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.0.0.tgz" }, "user-home": { "version": "1.1.1", - "from": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "from": "user-home@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz" }, "uuid": { "version": "2.0.1", - "from": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "from": "uuid@>=2.0.1 <3.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz" }, "xdg-basedir": { "version": "1.0.1", - "from": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-1.0.1.tgz", + "from": "xdg-basedir@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-1.0.1.tgz" } } }, "latest-version": { "version": "0.2.0", - "from": "https://registry.npmjs.org/latest-version/-/latest-version-0.2.0.tgz", + "from": "latest-version@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-0.2.0.tgz", "dependencies": { "package-json": { "version": "0.2.0", - "from": "https://registry.npmjs.org/package-json/-/package-json-0.2.0.tgz", + "from": "package-json@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/package-json/-/package-json-0.2.0.tgz", "dependencies": { "got": { "version": "0.3.0", - "from": "https://registry.npmjs.org/got/-/got-0.3.0.tgz", + "from": "got@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/got/-/got-0.3.0.tgz", "dependencies": { "object-assign": { "version": "0.3.1", - "from": "https://registry.npmjs.org/object-assign/-/object-assign-0.3.1.tgz", + "from": "object-assign@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-0.3.1.tgz" } } }, "registry-url": { "version": "0.1.1", - "from": "https://registry.npmjs.org/registry-url/-/registry-url-0.1.1.tgz", + "from": "registry-url@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-0.1.1.tgz", "dependencies": { "npmconf": { "version": "2.1.1", - "from": "https://registry.npmjs.org/npmconf/-/npmconf-2.1.1.tgz", + "from": "npmconf@>=2.0.1 <3.0.0", "resolved": "https://registry.npmjs.org/npmconf/-/npmconf-2.1.1.tgz", "dependencies": { "config-chain": { "version": "1.1.8", - "from": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.8.tgz", + "from": "config-chain@>=1.1.8 <1.2.0", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.8.tgz", "dependencies": { "proto-list": { "version": "1.2.3", - "from": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.3.tgz", + "from": "proto-list@>=1.2.1 <1.3.0", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.3.tgz" } } }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "ini": { "version": "1.3.3", - "from": "https://registry.npmjs.org/ini/-/ini-1.3.3.tgz", + "from": "ini@>=1.2.0 <2.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.3.tgz" }, "once": { "version": "1.3.1", - "from": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "from": "once@>=1.3.0 <2.0.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } }, "uid-number": { "version": "0.0.5", - "from": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.5.tgz", + "from": "uid-number@0.0.5", "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.5.tgz" } } @@ -3068,22 +3152,22 @@ }, "semver-diff": { "version": "0.1.0", - "from": "https://registry.npmjs.org/semver-diff/-/semver-diff-0.1.0.tgz", + "from": "semver-diff@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-0.1.0.tgz" }, "string-length": { "version": "0.1.2", - "from": "https://registry.npmjs.org/string-length/-/string-length-0.1.2.tgz", + "from": "string-length@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/string-length/-/string-length-0.1.2.tgz", "dependencies": { "strip-ansi": { "version": "0.2.2", - "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.2.2.tgz", + "from": "strip-ansi@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.2.2.tgz", "dependencies": { "ansi-regex": { "version": "0.1.0", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.1.0.tgz", + "from": "ansi-regex@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.1.0.tgz" } } @@ -3093,137 +3177,194 @@ } }, "which": { - "version": "1.0.8", - "from": "https://registry.npmjs.org/which/-/which-1.0.8.tgz", - "resolved": "https://registry.npmjs.org/which/-/which-1.0.8.tgz" + "version": "1.0.9", + "from": "which@>=1.0.5 <1.1.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz" } } }, "browserstacktunnel-wrapper": { "version": "1.3.1", - "from": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-1.3.1.tgz", + "from": "browserstacktunnel-wrapper@>=1.3.1 <1.4.0", "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-1.3.1.tgz", "dependencies": { "unzip": { "version": "0.1.11", - "from": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz", + "from": "unzip@>=0.1.9 <0.2.0", "resolved": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz", "dependencies": { "fstream": { "version": "0.1.31", - "from": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", + "from": "fstream@>=0.1.30 <1.0.0", "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", "dependencies": { "graceful-fs": { - "version": "3.0.5", - "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz" + "version": "3.0.6", + "from": "graceful-fs@>=3.0.2 <3.1.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.6.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "mkdirp": { "version": "0.5.0", - "from": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "from": "mkdirp@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "from": "minimist@0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "rimraf": { - "version": "2.2.8", - "from": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" + "version": "2.3.2", + "from": "rimraf@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.3.2.tgz", + "dependencies": { + "glob": { + "version": "4.5.3", + "from": "glob@>=4.4.2 <5.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "dependencies": { + "inflight": { + "version": "1.0.4", + "from": "inflight@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.1", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" + } + } + }, + "minimatch": { + "version": "2.0.4", + "from": "minimatch@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.4.tgz", + "dependencies": { + "brace-expansion": { + "version": "1.1.0", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", + "dependencies": { + "balanced-match": { + "version": "0.2.0", + "from": "balanced-match@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + } + } + } + } + }, + "once": { + "version": "1.3.1", + "from": "once@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.1", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" + } + } + } + } + } + } } } }, "pullstream": { "version": "0.4.1", - "from": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", + "from": "pullstream@>=0.4.1 <1.0.0", "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", "dependencies": { "over": { "version": "0.0.5", - "from": "https://registry.npmjs.org/over/-/over-0.0.5.tgz", + "from": "over@>=0.0.5 <1.0.0", "resolved": "https://registry.npmjs.org/over/-/over-0.0.5.tgz" }, "slice-stream": { "version": "1.0.0", - "from": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", + "from": "slice-stream@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz" } } }, "binary": { "version": "0.3.0", - "from": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "from": "binary@>=0.3.0 <1.0.0", "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", "dependencies": { "chainsaw": { "version": "0.1.0", - "from": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "from": "chainsaw@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "dependencies": { "traverse": { "version": "0.3.9", - "from": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "from": "traverse@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz" } } }, "buffers": { "version": "0.1.1", - "from": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "from": "buffers@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz" } } }, "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.33-1 <1.1.0-0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "setimmediate": { "version": "1.0.2", - "from": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.2.tgz", + "from": "setimmediate@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.2.tgz" }, "match-stream": { "version": "0.0.2", - "from": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", + "from": "match-stream@>=0.0.2 <1.0.0", "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", "dependencies": { "buffers": { "version": "0.1.1", - "from": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "from": "buffers@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz" } } @@ -3234,33 +3375,33 @@ }, "canonical-path": { "version": "0.0.2", - "from": "https://registry.npmjs.org/canonical-path/-/canonical-path-0.0.2.tgz", + "from": "canonical-path@0.0.2", "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-0.0.2.tgz" }, "cheerio": { "version": "0.17.0", - "from": "https://registry.npmjs.org/cheerio/-/cheerio-0.17.0.tgz", + "from": "cheerio@>=0.17.0 <0.18.0", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.17.0.tgz", "dependencies": { "CSSselect": { "version": "0.4.1", - "from": "https://registry.npmjs.org/CSSselect/-/CSSselect-0.4.1.tgz", + "from": "CSSselect@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/CSSselect/-/CSSselect-0.4.1.tgz", "dependencies": { "CSSwhat": { "version": "0.4.7", - "from": "https://registry.npmjs.org/CSSwhat/-/CSSwhat-0.4.7.tgz", + "from": "CSSwhat@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/CSSwhat/-/CSSwhat-0.4.7.tgz" }, "domutils": { "version": "1.4.3", - "from": "https://registry.npmjs.org/domutils/-/domutils-1.4.3.tgz", + "from": "domutils@>=1.4.0 <1.5.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.4.3.tgz", "dependencies": { "domelementtype": { - "version": "1.1.3", - "from": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz" + "version": "1.3.0", + "from": "domelementtype@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz" } } } @@ -3268,71 +3409,71 @@ }, "entities": { "version": "1.1.1", - "from": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "from": "entities@>=1.1.1 <1.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz" }, "htmlparser2": { "version": "3.7.3", - "from": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.7.3.tgz", + "from": "htmlparser2@>=3.7.2 <3.8.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.7.3.tgz", "dependencies": { "domhandler": { "version": "2.2.1", - "from": "https://registry.npmjs.org/domhandler/-/domhandler-2.2.1.tgz", + "from": "domhandler@>=2.2.0 <2.3.0", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.2.1.tgz" }, "domutils": { "version": "1.5.1", - "from": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "from": "domutils@>=1.5.0 <1.6.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz" }, "domelementtype": { - "version": "1.1.3", - "from": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz" + "version": "1.3.0", + "from": "domelementtype@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz" }, "readable-stream": { "version": "1.1.13", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "from": "readable-stream@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "entities": { "version": "1.0.0", - "from": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "from": "entities@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz" } } }, "dom-serializer": { "version": "0.0.1", - "from": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.0.1.tgz", + "from": "dom-serializer@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.0.1.tgz", "dependencies": { "domelementtype": { "version": "1.1.3", - "from": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "from": "domelementtype@>=1.1.1 <1.2.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz" } } @@ -3341,101 +3482,101 @@ }, "dgeni": { "version": "0.4.1", - "from": "https://registry.npmjs.org/dgeni/-/dgeni-0.4.1.tgz", + "from": "dgeni@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/dgeni/-/dgeni-0.4.1.tgz", "dependencies": { "dependency-graph": { "version": "0.1.0", - "from": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.1.0.tgz", + "from": "dependency-graph@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.1.0.tgz", "dependencies": { "underscore": { "version": "1.4.4", - "from": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "from": "underscore@1.4.4", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz" } } }, "di": { "version": "0.0.1", - "from": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "from": "di@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz" }, "optimist": { "version": "0.6.1", - "from": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "from": "optimist@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "dependencies": { "wordwrap": { "version": "0.0.2", - "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "from": "wordwrap@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" }, "minimist": { "version": "0.0.10", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "from": "minimist@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } }, "q": { "version": "0.9.7", - "from": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "from": "q@>=0.9.7 <0.10.0", "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz" }, "validate.js": { "version": "0.2.0", - "from": "https://registry.npmjs.org/validate.js/-/validate.js-0.2.0.tgz", + "from": "validate.js@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/validate.js/-/validate.js-0.2.0.tgz" }, "winston": { "version": "0.7.3", - "from": "https://registry.npmjs.org/winston/-/winston-0.7.3.tgz", + "from": "winston@>=0.7.2 <0.8.0", "resolved": "https://registry.npmjs.org/winston/-/winston-0.7.3.tgz", "dependencies": { "async": { "version": "0.2.10", - "from": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "from": "async@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "colors": { "version": "0.6.2", - "from": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "from": "colors@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz" }, "cycle": { "version": "1.0.3", - "from": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "from": "cycle@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz" }, "eyes": { "version": "0.1.8", - "from": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "from": "eyes@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz" }, "pkginfo": { "version": "0.3.0", - "from": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.0.tgz", + "from": "pkginfo@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.0.tgz" }, "request": { "version": "2.16.6", - "from": "https://registry.npmjs.org/request/-/request-2.16.6.tgz", + "from": "request@>=2.16.0 <2.17.0", "resolved": "https://registry.npmjs.org/request/-/request-2.16.6.tgz", "dependencies": { "form-data": { "version": "0.0.10", - "from": "https://registry.npmjs.org/form-data/-/form-data-0.0.10.tgz", + "from": "form-data@>=0.0.3 <0.1.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.0.10.tgz", "dependencies": { "combined-stream": { "version": "0.0.7", - "from": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "from": "combined-stream@>=0.0.4 <0.1.0", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", "dependencies": { "delayed-stream": { "version": "0.0.5", - "from": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "from": "delayed-stream@0.0.5", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" } } @@ -3444,81 +3585,81 @@ }, "mime": { "version": "1.2.11", - "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "from": "mime@>=1.2.11 <1.3.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "hawk": { "version": "0.10.2", - "from": "https://registry.npmjs.org/hawk/-/hawk-0.10.2.tgz", + "from": "hawk@>=0.10.2 <0.11.0", "resolved": "https://registry.npmjs.org/hawk/-/hawk-0.10.2.tgz", "dependencies": { "hoek": { "version": "0.7.6", - "from": "https://registry.npmjs.org/hoek/-/hoek-0.7.6.tgz", + "from": "hoek@>=0.7.0 <0.8.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.7.6.tgz" }, "boom": { "version": "0.3.8", - "from": "https://registry.npmjs.org/boom/-/boom-0.3.8.tgz", + "from": "boom@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/boom/-/boom-0.3.8.tgz" }, "cryptiles": { "version": "0.1.3", - "from": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.1.3.tgz", + "from": "cryptiles@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.1.3.tgz" }, "sntp": { "version": "0.1.4", - "from": "https://registry.npmjs.org/sntp/-/sntp-0.1.4.tgz", + "from": "sntp@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.1.4.tgz" } } }, "node-uuid": { - "version": "1.4.2", - "from": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz" + "version": "1.4.3", + "from": "node-uuid@>=1.4.0 <1.5.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" }, "cookie-jar": { "version": "0.2.0", - "from": "https://registry.npmjs.org/cookie-jar/-/cookie-jar-0.2.0.tgz", + "from": "cookie-jar@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/cookie-jar/-/cookie-jar-0.2.0.tgz" }, "aws-sign": { "version": "0.2.0", - "from": "https://registry.npmjs.org/aws-sign/-/aws-sign-0.2.0.tgz", + "from": "aws-sign@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/aws-sign/-/aws-sign-0.2.0.tgz" }, "oauth-sign": { "version": "0.2.0", - "from": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.2.0.tgz", + "from": "oauth-sign@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.2.0.tgz" }, "forever-agent": { "version": "0.2.0", - "from": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.2.0.tgz", + "from": "forever-agent@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.2.0.tgz" }, "tunnel-agent": { "version": "0.2.0", - "from": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.2.0.tgz", + "from": "tunnel-agent@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.2.0.tgz" }, "json-stringify-safe": { "version": "3.0.0", - "from": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-3.0.0.tgz", + "from": "json-stringify-safe@>=3.0.0 <3.1.0", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-3.0.0.tgz" }, "qs": { "version": "0.5.6", - "from": "https://registry.npmjs.org/qs/-/qs-0.5.6.tgz", + "from": "qs@>=0.5.4 <0.6.0", "resolved": "https://registry.npmjs.org/qs/-/qs-0.5.6.tgz" } } }, "stack-trace": { "version": "0.0.9", - "from": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", + "from": "stack-trace@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz" } } @@ -3526,142 +3667,165 @@ } }, "dgeni-packages": { - "version": "0.10.10", - "from": "https://registry.npmjs.org/dgeni-packages/-/dgeni-packages-0.10.10.tgz", - "resolved": "https://registry.npmjs.org/dgeni-packages/-/dgeni-packages-0.10.10.tgz", + "version": "0.10.13", + "from": "dgeni-packages@>=0.10.0 <0.11.0", "dependencies": { "catharsis": { - "version": "0.7.1", - "from": "https://registry.npmjs.org/catharsis/-/catharsis-0.7.1.tgz", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.7.1.tgz" + "version": "0.8.6", + "from": "catharsis@>=0.8.1 <0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.6.tgz", + "dependencies": { + "underscore-contrib": { + "version": "0.3.0", + "from": "underscore-contrib@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz", + "dependencies": { + "underscore": { + "version": "1.6.0", + "from": "underscore@1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz" + } + } + } + } }, "change-case": { - "version": "2.2.0", - "from": "https://registry.npmjs.org/change-case/-/change-case-2.2.0.tgz", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-2.2.0.tgz", + "version": "2.3.0", + "from": "change-case@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-2.3.0.tgz", "dependencies": { "camel-case": { "version": "1.1.1", - "from": "https://registry.npmjs.org/camel-case/-/camel-case-1.1.1.tgz", + "from": "camel-case@>=1.1.1 <2.0.0", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-1.1.1.tgz" }, "constant-case": { "version": "1.1.0", - "from": "https://registry.npmjs.org/constant-case/-/constant-case-1.1.0.tgz", + "from": "constant-case@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-1.1.0.tgz" }, "dot-case": { "version": "1.1.1", - "from": "https://registry.npmjs.org/dot-case/-/dot-case-1.1.1.tgz", + "from": "dot-case@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-1.1.1.tgz" }, "is-lower-case": { "version": "1.1.1", - "from": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.1.tgz", + "from": "is-lower-case@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.1.tgz" }, "is-upper-case": { "version": "1.1.1", - "from": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.1.tgz", + "from": "is-upper-case@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.1.tgz" }, "lower-case": { "version": "1.1.2", - "from": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.2.tgz", + "from": "lower-case@>=1.1.1 <2.0.0", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.2.tgz" }, + "lower-case-first": { + "version": "1.0.0", + "from": "lower-case-first@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-1.0.0.tgz" + }, "param-case": { "version": "1.1.1", - "from": "https://registry.npmjs.org/param-case/-/param-case-1.1.1.tgz", + "from": "param-case@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/param-case/-/param-case-1.1.1.tgz" }, "pascal-case": { "version": "1.1.0", - "from": "https://registry.npmjs.org/pascal-case/-/pascal-case-1.1.0.tgz", + "from": "pascal-case@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-1.1.0.tgz" }, "path-case": { "version": "1.1.1", - "from": "https://registry.npmjs.org/path-case/-/path-case-1.1.1.tgz", + "from": "path-case@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/path-case/-/path-case-1.1.1.tgz" }, "sentence-case": { "version": "1.1.2", - "from": "https://registry.npmjs.org/sentence-case/-/sentence-case-1.1.2.tgz", + "from": "sentence-case@>=1.1.1 <2.0.0", "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-1.1.2.tgz" }, "snake-case": { "version": "1.1.1", - "from": "https://registry.npmjs.org/snake-case/-/snake-case-1.1.1.tgz", + "from": "snake-case@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-1.1.1.tgz" }, "swap-case": { "version": "1.1.0", - "from": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.0.tgz", + "from": "swap-case@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.0.tgz" }, "title-case": { "version": "1.1.0", - "from": "https://registry.npmjs.org/title-case/-/title-case-1.1.0.tgz", + "from": "title-case@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/title-case/-/title-case-1.1.0.tgz" }, "upper-case": { "version": "1.1.2", - "from": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.2.tgz", + "from": "upper-case@>=1.1.1 <2.0.0", "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.2.tgz" }, "upper-case-first": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.0.tgz" + "version": "1.1.1", + "from": "upper-case-first@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.1.tgz" } } }, "esprima": { - "version": "1.2.4", - "from": "https://registry.npmjs.org/esprima/-/esprima-1.2.4.tgz", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.4.tgz" + "version": "1.2.5", + "from": "esprima@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz" }, "estraverse": { - "version": "1.9.1", - "from": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.1.tgz", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.1.tgz" + "version": "1.9.3", + "from": "estraverse@>=1.5.1 <2.0.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz" }, "glob": { "version": "3.2.11", - "from": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "from": "glob@>=3.2.8 <3.3.0", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "htmlparser2": { "version": "3.8.2", - "from": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.2.tgz", + "from": "htmlparser2@>=3.7.3 <4.0.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.2.tgz", "dependencies": { "domhandler": { "version": "2.3.0", - "from": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "from": "domhandler@>=2.3.0 <2.4.0", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz" }, "domutils": { "version": "1.5.1", - "from": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "from": "domutils@>=1.5.0 <1.6.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", "dependencies": { "dom-serializer": { "version": "0.1.0", - "from": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "from": "dom-serializer@>=0.0.0 <1.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", "dependencies": { + "domelementtype": { + "version": "1.1.3", + "from": "domelementtype@>=1.1.1 <1.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz" + }, "entities": { "version": "1.1.1", - "from": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "from": "entities@>=1.1.1 <1.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz" } } @@ -3669,104 +3833,160 @@ } }, "domelementtype": { - "version": "1.1.3", - "from": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz" + "version": "1.3.0", + "from": "domelementtype@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz" }, "readable-stream": { "version": "1.1.13", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "from": "readable-stream@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "entities": { "version": "1.0.0", - "from": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "from": "entities@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz" } } }, "minimatch": { "version": "0.3.0", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "from": "minimatch@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "nunjucks": { - "version": "1.0.7", - "from": "https://registry.npmjs.org/nunjucks/-/nunjucks-1.0.7.tgz", - "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-1.0.7.tgz", + "version": "1.2.0", + "from": "nunjucks@>=1.2.0 <2.0.0", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-1.2.0.tgz", "dependencies": { "optimist": { "version": "0.6.1", - "from": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "from": "optimist@*", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "dependencies": { "wordwrap": { "version": "0.0.2", - "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "from": "wordwrap@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" }, "minimist": { "version": "0.0.10", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "from": "minimist@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } }, "chokidar": { - "version": "0.8.4", - "from": "https://registry.npmjs.org/chokidar/-/chokidar-0.8.4.tgz", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-0.8.4.tgz", + "version": "0.12.6", + "from": "chokidar@>=0.12.5 <0.13.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-0.12.6.tgz", "dependencies": { + "readdirp": { + "version": "1.3.0", + "from": "readdirp@>=1.3.0 <1.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-1.3.0.tgz", + "dependencies": { + "graceful-fs": { + "version": "2.0.3", + "from": "graceful-fs@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz" + }, + "minimatch": { + "version": "0.2.14", + "from": "minimatch@>=0.2.12 <0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "dependencies": { + "lru-cache": { + "version": "2.5.0", + "from": "lru-cache@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" + }, + "sigmund": { + "version": "1.0.0", + "from": "sigmund@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" + } + } + }, + "readable-stream": { + "version": "1.0.33", + "from": "readable-stream@>=1.0.26-2 <1.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.1", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + } + } + }, + "async-each": { + "version": "0.1.6", + "from": "async-each@>=0.1.5 <0.2.0", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-0.1.6.tgz" + }, "fsevents": { - "version": "0.2.1", - "from": "fsevents@git+https://github.com/pipobscure/fsevents#7dcdf9fa3f8956610fd6f69f72c67bace2de7138", - "resolved": "git+https://github.com/pipobscure/fsevents#7dcdf9fa3f8956610fd6f69f72c67bace2de7138", + "version": "0.3.5", + "from": "fsevents@>=0.3.1 <0.4.0", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-0.3.5.tgz", "dependencies": { "nan": { - "version": "0.8.0", - "from": "https://registry.npmjs.org/nan/-/nan-0.8.0.tgz", - "resolved": "https://registry.npmjs.org/nan/-/nan-0.8.0.tgz" + "version": "1.5.3", + "from": "nan@>=1.5.0 <1.6.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.5.3.tgz" } } - }, - "recursive-readdir": { - "version": "0.0.2", - "from": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-0.0.2.tgz", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-0.0.2.tgz" } } } @@ -3774,42 +3994,42 @@ }, "q-io": { "version": "1.10.9", - "from": "https://registry.npmjs.org/q-io/-/q-io-1.10.9.tgz", + "from": "q-io@>=1.10.9 <1.11.0", "resolved": "https://registry.npmjs.org/q-io/-/q-io-1.10.9.tgz", "dependencies": { "q": { "version": "0.9.7", - "from": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "from": "q@>=0.9.7 <0.10.0", "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz" }, "qs": { "version": "0.1.0", - "from": "https://registry.npmjs.org/qs/-/qs-0.1.0.tgz", + "from": "qs@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/qs/-/qs-0.1.0.tgz" }, "url2": { "version": "0.0.0", - "from": "https://registry.npmjs.org/url2/-/url2-0.0.0.tgz", + "from": "url2@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/url2/-/url2-0.0.0.tgz" }, "mime": { "version": "1.2.11", - "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "from": "mime@>=1.2.11 <1.3.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "mimeparse": { "version": "0.1.4", - "from": "https://registry.npmjs.org/mimeparse/-/mimeparse-0.1.4.tgz", + "from": "mimeparse@>=0.1.4 <0.2.0", "resolved": "https://registry.npmjs.org/mimeparse/-/mimeparse-0.1.4.tgz" }, "collections": { "version": "0.2.2", - "from": "https://registry.npmjs.org/collections/-/collections-0.2.2.tgz", + "from": "collections@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/collections/-/collections-0.2.2.tgz", "dependencies": { "weak-map": { "version": "1.0.0", - "from": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.0.tgz", + "from": "weak-map@1.0.0", "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.0.tgz" } } @@ -3818,52 +4038,52 @@ }, "winston": { "version": "0.7.3", - "from": "https://registry.npmjs.org/winston/-/winston-0.7.3.tgz", + "from": "winston@>=0.7.2 <0.8.0", "resolved": "https://registry.npmjs.org/winston/-/winston-0.7.3.tgz", "dependencies": { "async": { "version": "0.2.10", - "from": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "from": "async@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "colors": { "version": "0.6.2", - "from": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "from": "colors@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz" }, "cycle": { "version": "1.0.3", - "from": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "from": "cycle@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz" }, "eyes": { "version": "0.1.8", - "from": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "from": "eyes@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz" }, "pkginfo": { "version": "0.3.0", - "from": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.0.tgz", + "from": "pkginfo@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.0.tgz" }, "request": { "version": "2.16.6", - "from": "https://registry.npmjs.org/request/-/request-2.16.6.tgz", + "from": "request@>=2.16.0 <2.17.0", "resolved": "https://registry.npmjs.org/request/-/request-2.16.6.tgz", "dependencies": { "form-data": { "version": "0.0.10", - "from": "https://registry.npmjs.org/form-data/-/form-data-0.0.10.tgz", + "from": "form-data@>=0.0.3 <0.1.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.0.10.tgz", "dependencies": { "combined-stream": { "version": "0.0.7", - "from": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "from": "combined-stream@>=0.0.4 <0.1.0", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", "dependencies": { "delayed-stream": { "version": "0.0.5", - "from": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "from": "delayed-stream@0.0.5", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" } } @@ -3872,81 +4092,81 @@ }, "mime": { "version": "1.2.11", - "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "from": "mime@>=1.2.7 <1.3.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "hawk": { "version": "0.10.2", - "from": "https://registry.npmjs.org/hawk/-/hawk-0.10.2.tgz", + "from": "hawk@>=0.10.2 <0.11.0", "resolved": "https://registry.npmjs.org/hawk/-/hawk-0.10.2.tgz", "dependencies": { "hoek": { "version": "0.7.6", - "from": "https://registry.npmjs.org/hoek/-/hoek-0.7.6.tgz", + "from": "hoek@>=0.7.0 <0.8.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.7.6.tgz" }, "boom": { "version": "0.3.8", - "from": "https://registry.npmjs.org/boom/-/boom-0.3.8.tgz", + "from": "boom@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/boom/-/boom-0.3.8.tgz" }, "cryptiles": { "version": "0.1.3", - "from": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.1.3.tgz", + "from": "cryptiles@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.1.3.tgz" }, "sntp": { "version": "0.1.4", - "from": "https://registry.npmjs.org/sntp/-/sntp-0.1.4.tgz", + "from": "sntp@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.1.4.tgz" } } }, "node-uuid": { - "version": "1.4.2", - "from": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz" + "version": "1.4.3", + "from": "node-uuid@>=1.4.0 <1.5.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" }, "cookie-jar": { "version": "0.2.0", - "from": "https://registry.npmjs.org/cookie-jar/-/cookie-jar-0.2.0.tgz", + "from": "cookie-jar@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/cookie-jar/-/cookie-jar-0.2.0.tgz" }, "aws-sign": { "version": "0.2.0", - "from": "https://registry.npmjs.org/aws-sign/-/aws-sign-0.2.0.tgz", + "from": "aws-sign@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/aws-sign/-/aws-sign-0.2.0.tgz" }, "oauth-sign": { "version": "0.2.0", - "from": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.2.0.tgz", + "from": "oauth-sign@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.2.0.tgz" }, "forever-agent": { "version": "0.2.0", - "from": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.2.0.tgz", + "from": "forever-agent@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.2.0.tgz" }, "tunnel-agent": { "version": "0.2.0", - "from": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.2.0.tgz", + "from": "tunnel-agent@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.2.0.tgz" }, "json-stringify-safe": { "version": "3.0.0", - "from": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-3.0.0.tgz", + "from": "json-stringify-safe@>=3.0.0 <3.1.0", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-3.0.0.tgz" }, "qs": { "version": "0.5.6", - "from": "https://registry.npmjs.org/qs/-/qs-0.5.6.tgz", + "from": "qs@>=0.5.4 <0.6.0", "resolved": "https://registry.npmjs.org/qs/-/qs-0.5.6.tgz" } } }, "stack-trace": { "version": "0.0.9", - "from": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", + "from": "stack-trace@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz" } } @@ -3955,104 +4175,104 @@ }, "event-stream": { "version": "3.1.7", - "from": "https://registry.npmjs.org/event-stream/-/event-stream-3.1.7.tgz", + "from": "event-stream@>=3.1.0 <3.2.0", "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.1.7.tgz", "dependencies": { "through": { "version": "2.3.6", - "from": "https://registry.npmjs.org/through/-/through-2.3.6.tgz", + "from": "through@>=2.3.1 <2.4.0", "resolved": "https://registry.npmjs.org/through/-/through-2.3.6.tgz" }, "duplexer": { "version": "0.1.1", - "from": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "from": "duplexer@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz" }, "from": { "version": "0.1.3", - "from": "https://registry.npmjs.org/from/-/from-0.1.3.tgz", + "from": "from@>=0.0.0 <1.0.0", "resolved": "https://registry.npmjs.org/from/-/from-0.1.3.tgz" }, "map-stream": { "version": "0.1.0", - "from": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "from": "map-stream@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz" }, "pause-stream": { "version": "0.0.11", - "from": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "from": "pause-stream@0.0.11", "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz" }, "split": { "version": "0.2.10", - "from": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", + "from": "split@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz" }, "stream-combiner": { "version": "0.0.4", - "from": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "from": "stream-combiner@>=0.0.4 <0.1.0", "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz" } } }, "grunt": { "version": "0.4.5", - "from": "https://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz", + "from": "grunt@>=0.4.2 <0.5.0", "resolved": "https://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz", "dependencies": { "async": { "version": "0.1.22", - "from": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "from": "async@>=0.1.22 <0.2.0", "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz" }, "coffee-script": { "version": "1.3.3", - "from": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz", + "from": "coffee-script@>=1.3.3 <1.4.0", "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz" }, "colors": { "version": "0.6.2", - "from": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "from": "colors@>=0.6.2 <0.7.0", "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz" }, "dateformat": { "version": "1.0.2-1.2.3", - "from": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz", + "from": "dateformat@1.0.2-1.2.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz" }, "eventemitter2": { "version": "0.4.14", - "from": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "from": "eventemitter2@>=0.4.13 <0.5.0", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz" }, "findup-sync": { "version": "0.1.3", - "from": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "from": "findup-sync@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", "dependencies": { "glob": { "version": "3.2.11", - "from": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "from": "glob@>=3.2.9 <3.3.0", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "from": "minimatch@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -4061,144 +4281,144 @@ }, "lodash": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz", + "from": "lodash@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" } } }, "glob": { "version": "3.1.21", - "from": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "from": "glob@>=3.1.21 <3.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", "dependencies": { "graceful-fs": { "version": "1.2.3", - "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "from": "graceful-fs@>=1.2.0 <1.3.0", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz" }, "inherits": { "version": "1.0.0", - "from": "https://registry.npmjs.org/inherits/-/inherits-1.0.0.tgz", + "from": "inherits@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.0.tgz" } } }, "hooker": { "version": "0.2.3", - "from": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "from": "hooker@>=0.2.3 <0.3.0", "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz" }, "iconv-lite": { "version": "0.2.11", - "from": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz", + "from": "iconv-lite@>=0.2.11 <0.3.0", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz" }, "minimatch": { "version": "0.2.14", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "from": "minimatch@>=0.2.12 <0.3.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "nopt": { "version": "1.0.10", - "from": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "from": "nopt@>=1.0.10 <1.1.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", "dependencies": { "abbrev": { "version": "1.0.5", - "from": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz", + "from": "abbrev@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz" } } }, "rimraf": { "version": "2.2.8", - "from": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "from": "rimraf@>=2.2.8 <2.3.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" }, "lodash": { "version": "0.9.2", - "from": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", + "from": "lodash@>=0.9.2 <0.10.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz" }, "underscore.string": { "version": "2.2.1", - "from": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz", + "from": "underscore.string@>=2.2.1 <2.3.0", "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz" }, "which": { - "version": "1.0.8", - "from": "https://registry.npmjs.org/which/-/which-1.0.8.tgz", - "resolved": "https://registry.npmjs.org/which/-/which-1.0.8.tgz" + "version": "1.0.9", + "from": "which@>=1.0.5 <1.1.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz" }, "js-yaml": { "version": "2.0.5", - "from": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz", + "from": "js-yaml@>=2.0.5 <2.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz", "dependencies": { "argparse": { "version": "0.1.16", - "from": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz", + "from": "argparse@>=0.1.11 <0.2.0", "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz", "dependencies": { "underscore": { "version": "1.7.0", - "from": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "from": "underscore@>=1.7.0 <1.8.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz" }, "underscore.string": { "version": "2.4.0", - "from": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz", + "from": "underscore.string@>=2.4.0 <2.5.0", "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz" } } }, "esprima": { "version": "1.0.4", - "from": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "from": "esprima@>=1.0.2 <1.1.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz" } } }, "exit": { "version": "0.1.2", - "from": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "from": "exit@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" }, "getobject": { "version": "0.1.0", - "from": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "from": "getobject@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz" }, "grunt-legacy-util": { "version": "0.2.0", - "from": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz", + "from": "grunt-legacy-util@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz" }, "grunt-legacy-log": { "version": "0.1.1", - "from": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.1.tgz", + "from": "grunt-legacy-log@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.1.tgz", "dependencies": { "lodash": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz", + "from": "lodash@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" }, "underscore.string": { "version": "2.3.3", - "from": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "from": "underscore.string@>=2.3.3 <2.4.0", "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz" } } @@ -4207,71 +4427,71 @@ }, "grunt-bump": { "version": "0.0.17", - "from": "https://registry.npmjs.org/grunt-bump/-/grunt-bump-0.0.17.tgz", + "from": "grunt-bump@>=0.0.13 <0.1.0", "resolved": "https://registry.npmjs.org/grunt-bump/-/grunt-bump-0.0.17.tgz", "dependencies": { "semver": { "version": "2.3.2", - "from": "https://registry.npmjs.org/semver/-/semver-2.3.2.tgz", + "from": "semver@>=2.3.0 <2.4.0", "resolved": "https://registry.npmjs.org/semver/-/semver-2.3.2.tgz" } } }, "grunt-contrib-clean": { "version": "0.6.0", - "from": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-0.6.0.tgz", + "from": "grunt-contrib-clean@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-0.6.0.tgz", "dependencies": { "rimraf": { "version": "2.2.8", - "from": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "from": "rimraf@>=2.2.1 <2.3.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" } } }, "grunt-contrib-compress": { "version": "0.12.0", - "from": "https://registry.npmjs.org/grunt-contrib-compress/-/grunt-contrib-compress-0.12.0.tgz", + "from": "grunt-contrib-compress@>=0.12.0 <0.13.0", "resolved": "https://registry.npmjs.org/grunt-contrib-compress/-/grunt-contrib-compress-0.12.0.tgz", "dependencies": { "archiver": { "version": "0.11.0", - "from": "https://registry.npmjs.org/archiver/-/archiver-0.11.0.tgz", + "from": "archiver@>=0.11.0 <0.12.0", "resolved": "https://registry.npmjs.org/archiver/-/archiver-0.11.0.tgz", "dependencies": { "async": { "version": "0.9.0", - "from": "https://registry.npmjs.org/async/-/async-0.9.0.tgz", + "from": "async@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" }, "buffer-crc32": { "version": "0.2.5", - "from": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.5.tgz", + "from": "buffer-crc32@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.5.tgz" }, "glob": { "version": "3.2.11", - "from": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "from": "glob@>=3.2.9 <3.3.0", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "from": "minimatch@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -4280,59 +4500,59 @@ }, "lazystream": { "version": "0.1.0", - "from": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", + "from": "lazystream@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz" }, "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.33-1 <1.1.0-0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "tar-stream": { "version": "0.4.7", - "from": "https://registry.npmjs.org/tar-stream/-/tar-stream-0.4.7.tgz", + "from": "tar-stream@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-0.4.7.tgz", "dependencies": { "bl": { "version": "0.9.4", - "from": "https://registry.npmjs.org/bl/-/bl-0.9.4.tgz", + "from": "bl@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.4.tgz" }, "end-of-stream": { "version": "1.1.0", - "from": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.1.0.tgz", + "from": "end-of-stream@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.1.0.tgz", "dependencies": { "once": { "version": "1.3.1", - "from": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "from": "once@>=1.3.0 <1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -4341,25 +4561,25 @@ }, "xtend": { "version": "4.0.0", - "from": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz", + "from": "xtend@>=4.0.0 <5.0.0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" } } }, "zip-stream": { "version": "0.4.1", - "from": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.4.1.tgz", + "from": "zip-stream@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.4.1.tgz", "dependencies": { "compress-commons": { "version": "0.1.6", - "from": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.1.6.tgz", + "from": "compress-commons@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.1.6.tgz", "dependencies": { "crc32-stream": { - "version": "0.3.2", - "from": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.2.tgz", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.2.tgz" + "version": "0.3.3", + "from": "crc32-stream@>=0.3.1 <0.4.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.3.tgz" } } } @@ -4369,173 +4589,173 @@ }, "chalk": { "version": "0.5.1", - "from": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "from": "chalk@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "dependencies": { "ansi-styles": { "version": "1.1.0", - "from": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "from": "ansi-styles@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" }, "escape-string-regexp": { - "version": "1.0.2", - "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz" + "version": "1.0.3", + "from": "escape-string-regexp@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz" }, "has-ansi": { "version": "0.1.0", - "from": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "from": "has-ansi@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "from": "ansi-regex@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "strip-ansi": { "version": "0.3.0", - "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "from": "strip-ansi@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "from": "ansi-regex@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "supports-color": { "version": "0.2.0", - "from": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "from": "supports-color@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" } } }, "prettysize": { "version": "0.0.3", - "from": "https://registry.npmjs.org/prettysize/-/prettysize-0.0.3.tgz", + "from": "prettysize@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/prettysize/-/prettysize-0.0.3.tgz" } } }, "grunt-contrib-connect": { "version": "0.8.0", - "from": "https://registry.npmjs.org/grunt-contrib-connect/-/grunt-contrib-connect-0.8.0.tgz", + "from": "grunt-contrib-connect@>=0.8.0 <0.9.0", "resolved": "https://registry.npmjs.org/grunt-contrib-connect/-/grunt-contrib-connect-0.8.0.tgz", "dependencies": { "connect": { "version": "2.19.6", - "from": "https://registry.npmjs.org/connect/-/connect-2.19.6.tgz", + "from": "connect@>=2.19.5 <2.20.0", "resolved": "https://registry.npmjs.org/connect/-/connect-2.19.6.tgz", "dependencies": { "basic-auth-connect": { "version": "1.0.0", - "from": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", + "from": "basic-auth-connect@1.0.0", "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz" }, "body-parser": { "version": "1.3.1", - "from": "https://registry.npmjs.org/body-parser/-/body-parser-1.3.1.tgz", + "from": "body-parser@1.3.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.3.1.tgz", "dependencies": { "raw-body": { "version": "1.1.6", - "from": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.6.tgz", + "from": "raw-body@1.1.6", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.6.tgz" } } }, "bytes": { "version": "1.0.0", - "from": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", + "from": "bytes@1.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz" }, "cookie": { "version": "0.1.2", - "from": "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz", + "from": "cookie@0.1.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz" }, "cookie-parser": { "version": "1.1.0", - "from": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.1.0.tgz", + "from": "cookie-parser@1.1.0", "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.1.0.tgz" }, "cookie-signature": { "version": "1.0.3", - "from": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.3.tgz", + "from": "cookie-signature@1.0.3", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.3.tgz" }, "compression": { "version": "1.0.7", - "from": "https://registry.npmjs.org/compression/-/compression-1.0.7.tgz", + "from": "compression@1.0.7", "resolved": "https://registry.npmjs.org/compression/-/compression-1.0.7.tgz", "dependencies": { "accepts": { "version": "1.0.3", - "from": "https://registry.npmjs.org/accepts/-/accepts-1.0.3.tgz", + "from": "accepts@1.0.3", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.0.3.tgz", "dependencies": { "mime": { "version": "1.2.11", - "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "from": "mime@1.2.11", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "negotiator": { "version": "0.4.6", - "from": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.6.tgz", + "from": "negotiator@0.4.6", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.6.tgz" } } }, "compressible": { "version": "1.1.0", - "from": "https://registry.npmjs.org/compressible/-/compressible-1.1.0.tgz", + "from": "compressible@1.1.0", "resolved": "https://registry.npmjs.org/compressible/-/compressible-1.1.0.tgz" }, "vary": { "version": "0.1.0", - "from": "https://registry.npmjs.org/vary/-/vary-0.1.0.tgz", + "from": "vary@0.1.0", "resolved": "https://registry.npmjs.org/vary/-/vary-0.1.0.tgz" } } }, "connect-timeout": { "version": "1.1.0", - "from": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.1.0.tgz", + "from": "connect-timeout@1.1.0", "resolved": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.1.0.tgz", "dependencies": { "debug": { "version": "0.8.1", - "from": "https://registry.npmjs.org/debug/-/debug-0.8.1.tgz", + "from": "debug@0.8.1", "resolved": "https://registry.npmjs.org/debug/-/debug-0.8.1.tgz" } } }, "csurf": { "version": "1.2.1", - "from": "https://registry.npmjs.org/csurf/-/csurf-1.2.1.tgz", + "from": "csurf@1.2.1", "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.2.1.tgz", "dependencies": { "csrf-tokens": { "version": "1.0.4", - "from": "https://registry.npmjs.org/csrf-tokens/-/csrf-tokens-1.0.4.tgz", + "from": "csrf-tokens@>=1.0.2 <1.1.0", "resolved": "https://registry.npmjs.org/csrf-tokens/-/csrf-tokens-1.0.4.tgz", "dependencies": { "rndm": { "version": "1.1.0", - "from": "https://registry.npmjs.org/rndm/-/rndm-1.1.0.tgz", + "from": "rndm@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.1.0.tgz" }, "uid2": { "version": "0.0.3", - "from": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", + "from": "uid2@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz" }, "scmp": { "version": "0.0.3", - "from": "https://registry.npmjs.org/scmp/-/scmp-0.0.3.tgz", + "from": "scmp@>=0.0.3 <0.1.0", "resolved": "https://registry.npmjs.org/scmp/-/scmp-0.0.3.tgz" } } @@ -4544,203 +4764,203 @@ }, "debug": { "version": "1.0.2", - "from": "https://registry.npmjs.org/debug/-/debug-1.0.2.tgz", + "from": "debug@1.0.2", "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.2.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "from": "ms@0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } }, "errorhandler": { "version": "1.0.2", - "from": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.0.2.tgz", + "from": "errorhandler@1.0.2", "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.0.2.tgz" }, "escape-html": { "version": "1.0.1", - "from": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz", + "from": "escape-html@1.0.1", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz" }, "express-session": { "version": "1.2.1", - "from": "https://registry.npmjs.org/express-session/-/express-session-1.2.1.tgz", + "from": "express-session@1.2.1", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.2.1.tgz", "dependencies": { "utils-merge": { "version": "1.0.0", - "from": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "from": "utils-merge@1.0.0", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" }, "uid2": { "version": "0.0.3", - "from": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", + "from": "uid2@0.0.3", "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz" }, "buffer-crc32": { "version": "0.2.1", - "from": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.1.tgz", + "from": "buffer-crc32@0.2.1", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.1.tgz" }, "debug": { "version": "0.8.1", - "from": "https://registry.npmjs.org/debug/-/debug-0.8.1.tgz", + "from": "debug@0.8.1", "resolved": "https://registry.npmjs.org/debug/-/debug-0.8.1.tgz" } } }, "fresh": { "version": "0.2.2", - "from": "https://registry.npmjs.org/fresh/-/fresh-0.2.2.tgz", + "from": "fresh@0.2.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.2.tgz" }, "method-override": { "version": "2.0.2", - "from": "https://registry.npmjs.org/method-override/-/method-override-2.0.2.tgz", + "from": "method-override@2.0.2", "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.0.2.tgz", "dependencies": { "methods": { "version": "1.0.1", - "from": "https://registry.npmjs.org/methods/-/methods-1.0.1.tgz", + "from": "methods@1.0.1", "resolved": "https://registry.npmjs.org/methods/-/methods-1.0.1.tgz" }, "vary": { "version": "0.1.0", - "from": "https://registry.npmjs.org/vary/-/vary-0.1.0.tgz", + "from": "vary@0.1.0", "resolved": "https://registry.npmjs.org/vary/-/vary-0.1.0.tgz" } } }, "morgan": { "version": "1.1.1", - "from": "https://registry.npmjs.org/morgan/-/morgan-1.1.1.tgz", + "from": "morgan@1.1.1", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.1.1.tgz" }, "multiparty": { "version": "3.2.8", - "from": "https://registry.npmjs.org/multiparty/-/multiparty-3.2.8.tgz", + "from": "multiparty@3.2.8", "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-3.2.8.tgz", "dependencies": { "readable-stream": { "version": "1.1.13", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "from": "readable-stream@>=1.1.9 <1.2.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "stream-counter": { "version": "0.2.0", - "from": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", + "from": "stream-counter@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz" } } }, "on-headers": { "version": "0.0.0", - "from": "https://registry.npmjs.org/on-headers/-/on-headers-0.0.0.tgz", + "from": "on-headers@0.0.0", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-0.0.0.tgz" }, "parseurl": { "version": "1.0.1", - "from": "https://registry.npmjs.org/parseurl/-/parseurl-1.0.1.tgz", + "from": "parseurl@1.0.1", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.0.1.tgz" }, "qs": { "version": "0.6.6", - "from": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz", + "from": "qs@0.6.6", "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz" }, "response-time": { "version": "2.0.0", - "from": "https://registry.npmjs.org/response-time/-/response-time-2.0.0.tgz", + "from": "response-time@2.0.0", "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.0.0.tgz" }, "serve-favicon": { "version": "2.0.1", - "from": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.0.1.tgz", + "from": "serve-favicon@2.0.1", "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.0.1.tgz" }, "serve-index": { "version": "1.1.1", - "from": "https://registry.npmjs.org/serve-index/-/serve-index-1.1.1.tgz", + "from": "serve-index@1.1.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.1.1.tgz", "dependencies": { "accepts": { "version": "1.0.3", - "from": "https://registry.npmjs.org/accepts/-/accepts-1.0.3.tgz", + "from": "accepts@1.0.3", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.0.3.tgz", "dependencies": { "mime": { "version": "1.2.11", - "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "from": "mime@>=1.2.11 <1.3.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "negotiator": { "version": "0.4.6", - "from": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.6.tgz", + "from": "negotiator@0.4.6", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.6.tgz" } } }, "batch": { "version": "0.5.0", - "from": "https://registry.npmjs.org/batch/-/batch-0.5.0.tgz", + "from": "batch@0.5.0", "resolved": "https://registry.npmjs.org/batch/-/batch-0.5.0.tgz" } } }, "serve-static": { "version": "1.2.3", - "from": "https://registry.npmjs.org/serve-static/-/serve-static-1.2.3.tgz", + "from": "serve-static@1.2.3", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.2.3.tgz", "dependencies": { "send": { "version": "0.4.3", - "from": "https://registry.npmjs.org/send/-/send-0.4.3.tgz", + "from": "send@0.4.3", "resolved": "https://registry.npmjs.org/send/-/send-0.4.3.tgz", "dependencies": { "finished": { "version": "1.2.2", - "from": "https://registry.npmjs.org/finished/-/finished-1.2.2.tgz", + "from": "finished@1.2.2", "resolved": "https://registry.npmjs.org/finished/-/finished-1.2.2.tgz", "dependencies": { "ee-first": { "version": "1.0.3", - "from": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.3.tgz", + "from": "ee-first@1.0.3", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.3.tgz" } } }, "mime": { "version": "1.2.11", - "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "from": "mime@1.2.11", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "range-parser": { "version": "1.0.2", - "from": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz", + "from": "range-parser@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz" } } @@ -4749,104 +4969,104 @@ }, "type-is": { "version": "1.2.1", - "from": "https://registry.npmjs.org/type-is/-/type-is-1.2.1.tgz", + "from": "type-is@1.2.1", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.2.1.tgz", "dependencies": { "mime-types": { "version": "1.0.0", - "from": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.0.tgz", + "from": "mime-types@1.0.0", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.0.tgz" } } }, "vhost": { "version": "1.0.0", - "from": "https://registry.npmjs.org/vhost/-/vhost-1.0.0.tgz", + "from": "vhost@1.0.0", "resolved": "https://registry.npmjs.org/vhost/-/vhost-1.0.0.tgz" }, "pause": { "version": "0.0.1", - "from": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "from": "pause@0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz" } } }, "connect-livereload": { "version": "0.4.1", - "from": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.4.1.tgz", + "from": "connect-livereload@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.4.1.tgz" }, "open": { "version": "0.0.5", - "from": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", + "from": "open@0.0.5", "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz" }, "portscanner": { "version": "0.2.3", - "from": "https://registry.npmjs.org/portscanner/-/portscanner-0.2.3.tgz", + "from": "portscanner@>=0.2.3 <0.3.0", "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-0.2.3.tgz", "dependencies": { "async": { "version": "0.1.15", - "from": "https://registry.npmjs.org/async/-/async-0.1.15.tgz", + "from": "async@0.1.15", "resolved": "https://registry.npmjs.org/async/-/async-0.1.15.tgz" } } }, "async": { "version": "0.9.0", - "from": "https://registry.npmjs.org/async/-/async-0.9.0.tgz", + "from": "async@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" } } }, "grunt-contrib-copy": { "version": "0.6.0", - "from": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-0.6.0.tgz", + "from": "grunt-contrib-copy@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-0.6.0.tgz", "dependencies": { "chalk": { "version": "0.5.1", - "from": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "from": "chalk@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "dependencies": { "ansi-styles": { "version": "1.1.0", - "from": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "from": "ansi-styles@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" }, "escape-string-regexp": { - "version": "1.0.2", - "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz" + "version": "1.0.3", + "from": "escape-string-regexp@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz" }, "has-ansi": { "version": "0.1.0", - "from": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "from": "has-ansi@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "from": "ansi-regex@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "strip-ansi": { "version": "0.3.0", - "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "from": "strip-ansi@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "from": "ansi-regex@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "supports-color": { "version": "0.2.0", - "from": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "from": "supports-color@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" } } @@ -4855,42 +5075,42 @@ }, "grunt-contrib-jshint": { "version": "0.10.0", - "from": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-0.10.0.tgz", + "from": "grunt-contrib-jshint@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-0.10.0.tgz", "dependencies": { "jshint": { "version": "2.5.11", - "from": "https://registry.npmjs.org/jshint/-/jshint-2.5.11.tgz", + "from": "jshint@>=2.5.0 <2.6.0", "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.5.11.tgz", "dependencies": { "cli": { - "version": "0.6.5", - "from": "https://registry.npmjs.org/cli/-/cli-0.6.5.tgz", - "resolved": "https://registry.npmjs.org/cli/-/cli-0.6.5.tgz", + "version": "0.6.6", + "from": "cli@>=0.6.0 <0.7.0", + "resolved": "https://registry.npmjs.org/cli/-/cli-0.6.6.tgz", "dependencies": { "glob": { "version": "3.2.11", - "from": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "from": "glob@>=3.2.1 <3.3.0", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "from": "minimatch@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -4901,44 +5121,49 @@ }, "console-browserify": { "version": "1.1.0", - "from": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "from": "console-browserify@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "dependencies": { "date-now": { "version": "0.1.4", - "from": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "from": "date-now@>=0.1.4 <0.2.0", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz" } } }, "exit": { "version": "0.1.2", - "from": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "from": "exit@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" }, "htmlparser2": { "version": "3.8.2", - "from": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.2.tgz", + "from": "htmlparser2@>=3.8.0 <3.9.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.2.tgz", "dependencies": { "domhandler": { "version": "2.3.0", - "from": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "from": "domhandler@>=2.3.0 <2.4.0", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz" }, "domutils": { "version": "1.5.1", - "from": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "from": "domutils@>=1.5.0 <1.6.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", "dependencies": { "dom-serializer": { "version": "0.1.0", - "from": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "from": "dom-serializer@>=0.0.0 <1.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", "dependencies": { + "domelementtype": { + "version": "1.1.3", + "from": "domelementtype@>=1.1.1 <1.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz" + }, "entities": { "version": "1.1.1", - "from": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "from": "entities@>=1.1.1 <1.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz" } } @@ -4946,187 +5171,187 @@ } }, "domelementtype": { - "version": "1.1.3", - "from": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz" + "version": "1.3.0", + "from": "domelementtype@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz" }, "readable-stream": { "version": "1.1.13", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "from": "readable-stream@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "entities": { "version": "1.0.0", - "from": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "from": "entities@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz" } } }, "minimatch": { "version": "1.0.0", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", + "from": "minimatch@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "strip-json-comments": { "version": "1.0.2", - "from": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.2.tgz", + "from": "strip-json-comments@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.2.tgz" }, "underscore": { "version": "1.6.0", - "from": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "from": "underscore@>=1.6.0 <1.7.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz" } } }, "hooker": { "version": "0.2.3", - "from": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "from": "hooker@>=0.2.3 <0.3.0", "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz" } } }, "grunt-ddescribe-iit": { "version": "0.0.6", - "from": "https://registry.npmjs.org/grunt-ddescribe-iit/-/grunt-ddescribe-iit-0.0.6.tgz", + "from": "grunt-ddescribe-iit@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/grunt-ddescribe-iit/-/grunt-ddescribe-iit-0.0.6.tgz", "dependencies": { "bluebird": { - "version": "2.9.12", - "from": "https://registry.npmjs.org/bluebird/-/bluebird-2.9.12.tgz", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.9.12.tgz" + "version": "2.9.24", + "from": "bluebird@>=2.9.9 <3.0.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.9.24.tgz" }, "win-spawn": { "version": "2.0.0", - "from": "https://registry.npmjs.org/win-spawn/-/win-spawn-2.0.0.tgz", + "from": "win-spawn@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/win-spawn/-/win-spawn-2.0.0.tgz" } } }, "grunt-jasmine-node": { "version": "0.1.0", - "from": "grunt-jasmine-node@git://github.com/vojtajina/grunt-jasmine-node.git#ced17cbe52c1412b2ada53160432a5b681f37cd7", + "from": "../../../../../var/folders/gl/40dc6sj56mq3yzwyghl869vc0000gn/T/npm-67032-57ebb73e/git-cache-9ddf46c895a6/ced17cbe52c1412b2ada53160432a5b681f37cd7", "resolved": "git://github.com/vojtajina/grunt-jasmine-node.git#ced17cbe52c1412b2ada53160432a5b681f37cd7" }, "grunt-jscs": { "version": "1.2.0", - "from": "https://registry.npmjs.org/grunt-jscs/-/grunt-jscs-1.2.0.tgz", + "from": "grunt-jscs@>=1.2.0 <1.3.0", "resolved": "https://registry.npmjs.org/grunt-jscs/-/grunt-jscs-1.2.0.tgz", "dependencies": { "hooker": { "version": "0.2.3", - "from": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "from": "hooker@>=0.2.3 <0.3.0", "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz" }, "jscs": { "version": "1.10.0", - "from": "https://registry.npmjs.org/jscs/-/jscs-1.10.0.tgz", + "from": "jscs@>=1.10.0 <1.11.0", "resolved": "https://registry.npmjs.org/jscs/-/jscs-1.10.0.tgz", "dependencies": { "colors": { "version": "1.0.3", - "from": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "from": "colors@>=1.0.3 <1.1.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz" }, "commander": { "version": "2.5.1", - "from": "https://registry.npmjs.org/commander/-/commander-2.5.1.tgz", + "from": "commander@>=2.5.0 <2.6.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.5.1.tgz" }, "esprima": { - "version": "1.2.4", - "from": "https://registry.npmjs.org/esprima/-/esprima-1.2.4.tgz", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.4.tgz" + "version": "1.2.5", + "from": "esprima@>=1.2.2 <1.3.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz" }, "esprima-harmony-jscs": { "version": "1.1.0-regex-token-fix", - "from": "https://registry.npmjs.org/esprima-harmony-jscs/-/esprima-harmony-jscs-1.1.0-regex-token-fix.tgz", + "from": "esprima-harmony-jscs@1.1.0-regex-token-fix", "resolved": "https://registry.npmjs.org/esprima-harmony-jscs/-/esprima-harmony-jscs-1.1.0-regex-token-fix.tgz" }, "estraverse": { - "version": "1.9.1", - "from": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.1.tgz", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.1.tgz" + "version": "1.9.3", + "from": "estraverse@>=1.9.0 <1.10.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz" }, "exit": { "version": "0.1.2", - "from": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "from": "exit@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" }, "glob": { "version": "4.0.6", - "from": "https://registry.npmjs.org/glob/-/glob-4.0.6.tgz", + "from": "glob@>=4.0.0 <4.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-4.0.6.tgz", "dependencies": { "graceful-fs": { - "version": "3.0.5", - "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz" + "version": "3.0.6", + "from": "graceful-fs@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.6.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "1.0.0", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", + "from": "minimatch@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "once": { "version": "1.3.1", - "from": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "from": "once@>=1.3.0 <2.0.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -5134,23 +5359,23 @@ } }, "minimatch": { - "version": "2.0.1", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.1.tgz", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.1.tgz", + "version": "2.0.4", + "from": "minimatch@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.4.tgz", "dependencies": { "brace-expansion": { "version": "1.1.0", - "from": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", + "from": "brace-expansion@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", "dependencies": { "balanced-match": { "version": "0.2.0", - "from": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz", + "from": "balanced-match@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz" }, "concat-map": { "version": "0.0.1", - "from": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "from": "concat-map@0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" } } @@ -5159,54 +5384,54 @@ }, "strip-json-comments": { "version": "1.0.2", - "from": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.2.tgz", + "from": "strip-json-comments@>=1.0.1 <1.1.0", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.2.tgz" }, "vow-fs": { "version": "0.3.4", - "from": "https://registry.npmjs.org/vow-fs/-/vow-fs-0.3.4.tgz", + "from": "vow-fs@>=0.3.1 <0.4.0", "resolved": "https://registry.npmjs.org/vow-fs/-/vow-fs-0.3.4.tgz", "dependencies": { "node-uuid": { - "version": "1.4.2", - "from": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz" + "version": "1.4.3", + "from": "node-uuid@>=1.4.2 <2.0.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" }, "vow-queue": { "version": "0.4.1", - "from": "https://registry.npmjs.org/vow-queue/-/vow-queue-0.4.1.tgz", + "from": "vow-queue@>=0.4.1 <0.5.0", "resolved": "https://registry.npmjs.org/vow-queue/-/vow-queue-0.4.1.tgz" }, "glob": { - "version": "4.4.0", - "from": "https://registry.npmjs.org/glob/-/glob-4.4.0.tgz", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.4.0.tgz", + "version": "4.5.3", + "from": "glob@>=4.3.1 <5.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", "dependencies": { "inflight": { "version": "1.0.4", - "from": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", + "from": "inflight@>=1.0.4 <2.0.0", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "once": { "version": "1.3.1", - "from": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "from": "once@>=1.3.0 <2.0.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -5217,83 +5442,88 @@ }, "xmlbuilder": { "version": "2.4.6", - "from": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.4.6.tgz", + "from": "xmlbuilder@>=2.4.0 <2.5.0", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.4.6.tgz", "dependencies": { "lodash-node": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash-node/-/lodash-node-2.4.1.tgz", + "from": "lodash-node@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash-node/-/lodash-node-2.4.1.tgz" } } }, "supports-color": { - "version": "1.2.0", - "from": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz" + "version": "1.2.1", + "from": "supports-color@>=1.2.0 <1.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.1.tgz" } } }, "vow": { - "version": "0.4.8", - "from": "https://registry.npmjs.org/vow/-/vow-0.4.8.tgz", - "resolved": "https://registry.npmjs.org/vow/-/vow-0.4.8.tgz" + "version": "0.4.9", + "from": "vow@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/vow/-/vow-0.4.9.tgz" } } }, "grunt-merge-conflict": { "version": "0.0.2", - "from": "https://registry.npmjs.org/grunt-merge-conflict/-/grunt-merge-conflict-0.0.2.tgz", + "from": "grunt-merge-conflict@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/grunt-merge-conflict/-/grunt-merge-conflict-0.0.2.tgz" }, "grunt-shell": { - "version": "1.1.1", - "from": "https://registry.npmjs.org/grunt-shell/-/grunt-shell-1.1.1.tgz", - "resolved": "https://registry.npmjs.org/grunt-shell/-/grunt-shell-1.1.1.tgz", + "version": "1.1.2", + "from": "grunt-shell@>=1.1.1 <1.2.0", + "resolved": "https://registry.npmjs.org/grunt-shell/-/grunt-shell-1.1.2.tgz", "dependencies": { "chalk": { - "version": "0.5.1", - "from": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "version": "1.0.0", + "from": "chalk@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.0.0.tgz", "dependencies": { "ansi-styles": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" + "version": "2.0.1", + "from": "ansi-styles@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.0.1.tgz" }, "escape-string-regexp": { - "version": "1.0.2", - "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz" + "version": "1.0.3", + "from": "escape-string-regexp@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz" }, "has-ansi": { - "version": "0.1.0", - "from": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "version": "1.0.3", + "from": "has-ansi@>=1.0.3 <2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-1.0.3.tgz", "dependencies": { "ansi-regex": { - "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" + "version": "1.1.1", + "from": "ansi-regex@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz" + }, + "get-stdin": { + "version": "4.0.1", + "from": "get-stdin@>=4.0.1 <5.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" } } }, "strip-ansi": { - "version": "0.3.0", - "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "version": "2.0.1", + "from": "strip-ansi@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", "dependencies": { "ansi-regex": { - "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" + "version": "1.1.1", + "from": "ansi-regex@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz" } } }, "supports-color": { - "version": "0.2.0", - "from": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" + "version": "1.3.1", + "from": "supports-color@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz" } } } @@ -5301,125 +5531,125 @@ }, "gulp": { "version": "3.8.11", - "from": "https://registry.npmjs.org/gulp/-/gulp-3.8.11.tgz", + "from": "gulp@>=3.8.0 <3.9.0", "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.8.11.tgz", "dependencies": { "archy": { "version": "1.0.0", - "from": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "from": "archy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz" }, "chalk": { "version": "0.5.1", - "from": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "from": "chalk@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "dependencies": { "ansi-styles": { "version": "1.1.0", - "from": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "from": "ansi-styles@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" }, "escape-string-regexp": { - "version": "1.0.2", - "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz" + "version": "1.0.3", + "from": "escape-string-regexp@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz" }, "has-ansi": { "version": "0.1.0", - "from": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "from": "has-ansi@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "from": "ansi-regex@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "strip-ansi": { "version": "0.3.0", - "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "from": "strip-ansi@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "from": "ansi-regex@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "supports-color": { "version": "0.2.0", - "from": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "from": "supports-color@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" } } }, "deprecated": { "version": "0.0.1", - "from": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "from": "deprecated@>=0.0.1 <0.0.2", "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz" }, "interpret": { "version": "0.3.10", - "from": "https://registry.npmjs.org/interpret/-/interpret-0.3.10.tgz", + "from": "interpret@>=0.3.2 <0.4.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.3.10.tgz" }, "liftoff": { - "version": "2.0.1", - "from": "https://registry.npmjs.org/liftoff/-/liftoff-2.0.1.tgz", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.0.1.tgz", + "version": "2.0.3", + "from": "liftoff@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.0.3.tgz", "dependencies": { "extend": { - "version": "1.3.0", - "from": "https://registry.npmjs.org/extend/-/extend-1.3.0.tgz", - "resolved": "https://registry.npmjs.org/extend/-/extend-1.3.0.tgz" + "version": "2.0.0", + "from": "extend@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-2.0.0.tgz" }, "findup-sync": { "version": "0.2.1", - "from": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.2.1.tgz", + "from": "findup-sync@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.2.1.tgz", "dependencies": { "glob": { "version": "4.3.5", - "from": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz", + "from": "glob@>=4.3.0 <4.4.0", "resolved": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz", "dependencies": { "inflight": { "version": "1.0.4", - "from": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", + "from": "inflight@>=1.0.4 <2.0.0", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { - "version": "2.0.1", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.1.tgz", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.1.tgz", + "version": "2.0.4", + "from": "minimatch@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.4.tgz", "dependencies": { "brace-expansion": { "version": "1.1.0", - "from": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", + "from": "brace-expansion@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", "dependencies": { "balanced-match": { "version": "0.2.0", - "from": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz", + "from": "balanced-match@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz" }, "concat-map": { "version": "0.0.1", - "from": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "from": "concat-map@0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" } } @@ -5428,12 +5658,12 @@ }, "once": { "version": "1.3.1", - "from": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "from": "once@>=1.3.0 <2.0.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -5444,39 +5674,39 @@ }, "flagged-respawn": { "version": "0.3.1", - "from": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.1.tgz", + "from": "flagged-respawn@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.1.tgz" }, "resolve": { - "version": "1.0.0", - "from": "https://registry.npmjs.org/resolve/-/resolve-1.0.0.tgz", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.0.0.tgz" + "version": "1.1.6", + "from": "resolve@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.6.tgz" } } }, "minimist": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/minimist/-/minimist-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.0.tgz" + "version": "1.1.1", + "from": "minimist@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.1.tgz" }, "orchestrator": { "version": "0.3.7", - "from": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.7.tgz", + "from": "orchestrator@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.7.tgz", "dependencies": { "end-of-stream": { "version": "0.1.5", - "from": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "from": "end-of-stream@>=0.1.5 <0.2.0", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", "dependencies": { "once": { "version": "1.3.1", - "from": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "from": "once@>=1.3.0 <1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -5485,95 +5715,102 @@ }, "sequencify": { "version": "0.0.7", - "from": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "from": "sequencify@>=0.0.7 <0.1.0", "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz" }, "stream-consume": { "version": "0.1.0", - "from": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", + "from": "stream-consume@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz" } } }, "pretty-hrtime": { "version": "0.2.2", - "from": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-0.2.2.tgz", + "from": "pretty-hrtime@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-0.2.2.tgz" }, "semver": { - "version": "4.3.0", - "from": "https://registry.npmjs.org/semver/-/semver-4.3.0.tgz", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.0.tgz" + "version": "4.3.3", + "from": "semver@>=4.1.0 <5.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.3.tgz" }, "tildify": { "version": "1.0.0", - "from": "https://registry.npmjs.org/tildify/-/tildify-1.0.0.tgz", + "from": "tildify@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.0.0.tgz", "dependencies": { "user-home": { "version": "1.1.1", - "from": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "from": "user-home@>=1.1.1 <2.0.0", "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz" } } }, "v8flags": { - "version": "2.0.2", - "from": "https://registry.npmjs.org/v8flags/-/v8flags-2.0.2.tgz", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.0.2.tgz" + "version": "2.0.3", + "from": "v8flags@>=2.0.2 <3.0.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.0.3.tgz", + "dependencies": { + "user-home": { + "version": "1.1.1", + "from": "user-home@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz" + } + } }, "vinyl-fs": { "version": "0.3.13", - "from": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.13.tgz", + "from": "vinyl-fs@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.13.tgz", "dependencies": { "defaults": { - "version": "1.0.0", - "from": "https://registry.npmjs.org/defaults/-/defaults-1.0.0.tgz", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.0.tgz", + "version": "1.0.2", + "from": "defaults@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.2.tgz", "dependencies": { "clone": { "version": "0.1.19", - "from": "https://registry.npmjs.org/clone/-/clone-0.1.19.tgz", + "from": "clone@>=0.1.5 <0.2.0", "resolved": "https://registry.npmjs.org/clone/-/clone-0.1.19.tgz" } } }, "glob-stream": { "version": "3.1.18", - "from": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "from": "glob-stream@>=3.1.5 <4.0.0", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", "dependencies": { "glob": { - "version": "4.4.0", - "from": "https://registry.npmjs.org/glob/-/glob-4.4.0.tgz", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.4.0.tgz", + "version": "4.5.3", + "from": "glob@>=4.3.1 <5.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", "dependencies": { "inflight": { "version": "1.0.4", - "from": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", + "from": "inflight@>=1.0.4 <2.0.0", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "once": { "version": "1.3.1", - "from": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "from": "once@>=1.3.0 <2.0.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -5581,23 +5818,23 @@ } }, "minimatch": { - "version": "2.0.1", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.1.tgz", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.1.tgz", + "version": "2.0.4", + "from": "minimatch@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.4.tgz", "dependencies": { "brace-expansion": { "version": "1.1.0", - "from": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", + "from": "brace-expansion@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", "dependencies": { "balanced-match": { "version": "0.2.0", - "from": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz", + "from": "balanced-match@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz" }, "concat-map": { "version": "0.0.1", - "from": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "from": "concat-map@0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" } } @@ -5606,78 +5843,78 @@ }, "ordered-read-streams": { "version": "0.1.0", - "from": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "from": "ordered-read-streams@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz" }, "glob2base": { "version": "0.0.12", - "from": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "from": "glob2base@>=0.0.12 <0.0.13", "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", "dependencies": { "find-index": { "version": "0.1.1", - "from": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "from": "find-index@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz" } } }, "unique-stream": { "version": "1.0.0", - "from": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "from": "unique-stream@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz" } } }, "glob-watcher": { "version": "0.0.6", - "from": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "from": "glob-watcher@>=0.0.6 <0.0.7", "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", "dependencies": { "gaze": { "version": "0.5.1", - "from": "https://registry.npmjs.org/gaze/-/gaze-0.5.1.tgz", + "from": "gaze@>=0.5.1 <0.6.0", "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.1.tgz", "dependencies": { "globule": { "version": "0.1.0", - "from": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "from": "globule@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", "dependencies": { "lodash": { - "version": "1.0.1", - "from": "https://registry.npmjs.org/lodash/-/lodash-1.0.1.tgz", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.1.tgz" + "version": "1.0.2", + "from": "lodash@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz" }, "glob": { "version": "3.1.21", - "from": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "from": "glob@>=3.1.21 <3.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", "dependencies": { "graceful-fs": { "version": "1.2.3", - "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "from": "graceful-fs@>=1.2.0 <1.3.0", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz" }, "inherits": { "version": "1.0.0", - "from": "https://registry.npmjs.org/inherits/-/inherits-1.0.0.tgz", + "from": "inherits@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.0.tgz" } } }, "minimatch": { "version": "0.2.14", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "from": "minimatch@>=0.2.9 <0.3.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -5689,91 +5926,91 @@ } }, "graceful-fs": { - "version": "3.0.5", - "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz" + "version": "3.0.6", + "from": "graceful-fs@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.6.tgz" }, "mkdirp": { "version": "0.5.0", - "from": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "from": "mkdirp@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "from": "minimist@0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "strip-bom": { "version": "1.0.0", - "from": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "from": "strip-bom@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", "dependencies": { "first-chunk-stream": { "version": "1.0.0", - "from": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "from": "first-chunk-stream@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz" }, "is-utf8": { "version": "0.2.0", - "from": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.0.tgz", + "from": "is-utf8@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.0.tgz" } } }, "through2": { "version": "0.6.3", - "from": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", + "from": "through2@>=0.6.1 <0.7.0", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", "dependencies": { "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.33-1 <1.1.0-0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "xtend": { "version": "4.0.0", - "from": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz", + "from": "xtend@>=4.0.0 <4.1.0-0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" } } }, "vinyl": { "version": "0.4.6", - "from": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "from": "vinyl@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", "dependencies": { "clone": { "version": "0.2.0", - "from": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "from": "clone@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz" }, "clone-stats": { "version": "0.0.1", - "from": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "from": "clone-stats@>=0.0.1 <0.0.2", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" } } @@ -5783,23 +6020,23 @@ } }, "gulp-concat": { - "version": "2.5.1", - "from": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.5.1.tgz", - "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.5.1.tgz", + "version": "2.5.2", + "from": "gulp-concat@>=2.4.1 <3.0.0", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.5.2.tgz", "dependencies": { "concat-with-sourcemaps": { - "version": "1.0.0", - "from": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.0.tgz", - "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.0.tgz", + "version": "1.0.2", + "from": "concat-with-sourcemaps@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.2.tgz", "dependencies": { "source-map": { - "version": "0.1.43", - "from": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "version": "0.4.2", + "from": "source-map@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.2.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", + "from": "amdefine@>=0.0.4", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } @@ -5808,39 +6045,39 @@ }, "through2": { "version": "0.6.3", - "from": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", + "from": "through2@>=0.6.3 <0.7.0", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", "dependencies": { "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.33-1 <1.1.0-0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "xtend": { "version": "4.0.0", - "from": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz", + "from": "xtend@>=4.0.0 <4.1.0-0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" } } @@ -5849,105 +6086,105 @@ }, "gulp-foreach": { "version": "0.0.1", - "from": "https://registry.npmjs.org/gulp-foreach/-/gulp-foreach-0.0.1.tgz", + "from": "gulp-foreach@0.0.1", "resolved": "https://registry.npmjs.org/gulp-foreach/-/gulp-foreach-0.0.1.tgz", "dependencies": { "gulp-util": { "version": "2.2.20", - "from": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", + "from": "gulp-util@>=2.2.14 <2.3.0", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", "dependencies": { "chalk": { "version": "0.5.1", - "from": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "from": "chalk@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "dependencies": { "ansi-styles": { "version": "1.1.0", - "from": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "from": "ansi-styles@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" }, "escape-string-regexp": { - "version": "1.0.2", - "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz" + "version": "1.0.3", + "from": "escape-string-regexp@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz" }, "has-ansi": { "version": "0.1.0", - "from": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "from": "has-ansi@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "from": "ansi-regex@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "strip-ansi": { "version": "0.3.0", - "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "from": "strip-ansi@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "from": "ansi-regex@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "supports-color": { "version": "0.2.0", - "from": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "from": "supports-color@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" } } }, "dateformat": { "version": "1.0.11", - "from": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.11.tgz", + "from": "dateformat@>=1.0.7-1.2.3 <2.0.0", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.11.tgz", "dependencies": { "get-stdin": { "version": "4.0.1", - "from": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "from": "get-stdin@*", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" }, "meow": { - "version": "3.0.0", - "from": "https://registry.npmjs.org/meow/-/meow-3.0.0.tgz", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.0.0.tgz", + "version": "3.1.0", + "from": "meow@*", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.1.0.tgz", "dependencies": { "camelcase-keys": { "version": "1.0.0", - "from": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-1.0.0.tgz", + "from": "camelcase-keys@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-1.0.0.tgz", "dependencies": { "camelcase": { "version": "1.0.2", - "from": "https://registry.npmjs.org/camelcase/-/camelcase-1.0.2.tgz", + "from": "camelcase@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.0.2.tgz" }, "map-obj": { "version": "1.0.0", - "from": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.0.tgz", + "from": "map-obj@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.0.tgz" } } }, "indent-string": { "version": "1.2.1", - "from": "https://registry.npmjs.org/indent-string/-/indent-string-1.2.1.tgz", + "from": "indent-string@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-1.2.1.tgz", "dependencies": { "repeating": { "version": "1.1.2", - "from": "https://registry.npmjs.org/repeating/-/repeating-1.1.2.tgz", + "from": "repeating@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.2.tgz", "dependencies": { "is-finite": { "version": "1.0.0", - "from": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.0.tgz", + "from": "is-finite@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.0.tgz" } } @@ -5955,13 +6192,13 @@ } }, "minimist": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/minimist/-/minimist-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.0.tgz" + "version": "1.1.1", + "from": "minimist@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.1.tgz" }, "object-assign": { "version": "2.0.0", - "from": "https://registry.npmjs.org/object-assign/-/object-assign-2.0.0.tgz", + "from": "object-assign@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.0.0.tgz" } } @@ -5970,51 +6207,51 @@ }, "lodash._reinterpolate": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", + "from": "lodash._reinterpolate@>=2.4.1 <3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz" }, "lodash.template": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", + "from": "lodash.template@>=2.4.1 <3.0.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", "dependencies": { "lodash.defaults": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", + "from": "lodash.defaults@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } }, "lodash.escape": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", + "from": "lodash.escape@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", "dependencies": { "lodash._escapehtmlchar": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", + "from": "lodash._escapehtmlchar@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", "dependencies": { "lodash._htmlescapes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", + "from": "lodash._htmlescapes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz" } } }, "lodash._reunescapedhtml": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", + "from": "lodash._reunescapedhtml@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", "dependencies": { "lodash._htmlescapes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", + "from": "lodash._htmlescapes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz" } } @@ -6023,39 +6260,39 @@ }, "lodash._escapestringchar": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", + "from": "lodash._escapestringchar@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz" }, "lodash.keys": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "from": "lodash.keys@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "dependencies": { "lodash._isnative": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "from": "lodash._isnative@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" }, "lodash.isobject": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "from": "lodash.isobject@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } }, "lodash._shimkeys": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "from": "lodash._shimkeys@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } @@ -6064,54 +6301,54 @@ }, "lodash.templatesettings": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", + "from": "lodash.templatesettings@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz" }, "lodash.values": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", + "from": "lodash.values@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz" } } }, "minimist": { "version": "0.2.0", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "from": "minimist@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz" }, "multipipe": { "version": "0.1.2", - "from": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "from": "multipipe@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "dependencies": { "duplexer2": { "version": "0.0.2", - "from": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "from": "duplexer2@0.0.2", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "dependencies": { "readable-stream": { "version": "1.1.13", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "from": "readable-stream@>=1.1.9 <1.2.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } @@ -6122,51 +6359,51 @@ }, "through2": { "version": "0.5.1", - "from": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "from": "through2@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", "dependencies": { "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.17 <1.1.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "xtend": { "version": "3.0.0", - "from": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "from": "xtend@>=3.0.0 <3.1.0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz" } } }, "vinyl": { "version": "0.2.3", - "from": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", + "from": "vinyl@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", "dependencies": { "clone-stats": { "version": "0.0.1", - "from": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "from": "clone-stats@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" } } @@ -6175,81 +6412,81 @@ }, "through": { "version": "2.3.6", - "from": "https://registry.npmjs.org/through/-/through-2.3.6.tgz", + "from": "through@>=2.3.4 <2.4.0", "resolved": "https://registry.npmjs.org/through/-/through-2.3.6.tgz" } } }, "gulp-jshint": { "version": "1.4.2", - "from": "https://registry.npmjs.org/gulp-jshint/-/gulp-jshint-1.4.2.tgz", + "from": "gulp-jshint@>=1.4.2 <1.5.0", "resolved": "https://registry.npmjs.org/gulp-jshint/-/gulp-jshint-1.4.2.tgz", "dependencies": { "map-stream": { "version": "0.1.0", - "from": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "from": "map-stream@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz" }, "jshint": { "version": "2.4.4", - "from": "https://registry.npmjs.org/jshint/-/jshint-2.4.4.tgz", + "from": "jshint@>=2.4.3 <2.5.0", "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.4.4.tgz", "dependencies": { "shelljs": { "version": "0.1.4", - "from": "https://registry.npmjs.org/shelljs/-/shelljs-0.1.4.tgz", + "from": "shelljs@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.1.4.tgz" }, "underscore": { "version": "1.4.4", - "from": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "from": "underscore@>=1.4.0 <1.5.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz" }, "cli": { "version": "0.4.5", - "from": "https://registry.npmjs.org/cli/-/cli-0.4.5.tgz", + "from": "cli@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/cli/-/cli-0.4.5.tgz", "dependencies": { "glob": { - "version": "4.4.0", - "from": "https://registry.npmjs.org/glob/-/glob-4.4.0.tgz", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.4.0.tgz", + "version": "5.0.3", + "from": "glob@>=3.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.3.tgz", "dependencies": { "inflight": { "version": "1.0.4", - "from": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", + "from": "inflight@>=1.0.4 <2.0.0", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { - "version": "2.0.1", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.1.tgz", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.1.tgz", + "version": "2.0.4", + "from": "minimatch@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.4.tgz", "dependencies": { "brace-expansion": { "version": "1.1.0", - "from": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", + "from": "brace-expansion@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", "dependencies": { "balanced-match": { "version": "0.2.0", - "from": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz", + "from": "balanced-match@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz" }, "concat-map": { "version": "0.0.1", - "from": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "from": "concat-map@0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" } } @@ -6258,12 +6495,12 @@ }, "once": { "version": "1.3.1", - "from": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "from": "once@>=1.3.0 <2.0.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -6274,64 +6511,64 @@ }, "minimatch": { "version": "0.4.0", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.4.0.tgz", + "from": "minimatch@>=0.0.0 <1.0.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.4.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "htmlparser2": { "version": "3.3.0", - "from": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", + "from": "htmlparser2@>=3.3.0 <3.4.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", "dependencies": { "domhandler": { "version": "2.1.0", - "from": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz", + "from": "domhandler@>=2.1.0 <2.2.0", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz" }, "domutils": { "version": "1.1.6", - "from": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", + "from": "domutils@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz" }, "domelementtype": { - "version": "1.1.3", - "from": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz" + "version": "1.3.0", + "from": "domelementtype@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz" }, "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } @@ -6340,112 +6577,112 @@ }, "console-browserify": { "version": "0.1.6", - "from": "https://registry.npmjs.org/console-browserify/-/console-browserify-0.1.6.tgz", + "from": "console-browserify@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-0.1.6.tgz" }, "exit": { "version": "0.1.2", - "from": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "from": "exit@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" } } }, "gulp-util": { "version": "2.2.20", - "from": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", + "from": "gulp-util@>=2.2.14 <2.3.0", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", "dependencies": { "chalk": { "version": "0.5.1", - "from": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "from": "chalk@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "dependencies": { "ansi-styles": { "version": "1.1.0", - "from": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "from": "ansi-styles@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" }, "escape-string-regexp": { - "version": "1.0.2", - "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz" + "version": "1.0.3", + "from": "escape-string-regexp@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz" }, "has-ansi": { "version": "0.1.0", - "from": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "from": "has-ansi@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "from": "ansi-regex@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "strip-ansi": { "version": "0.3.0", - "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "from": "strip-ansi@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "from": "ansi-regex@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "supports-color": { "version": "0.2.0", - "from": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "from": "supports-color@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" } } }, "dateformat": { "version": "1.0.11", - "from": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.11.tgz", + "from": "dateformat@>=1.0.7-1.2.3 <2.0.0", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.11.tgz", "dependencies": { "get-stdin": { "version": "4.0.1", - "from": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "from": "get-stdin@*", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" }, "meow": { - "version": "3.0.0", - "from": "https://registry.npmjs.org/meow/-/meow-3.0.0.tgz", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.0.0.tgz", + "version": "3.1.0", + "from": "meow@*", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.1.0.tgz", "dependencies": { "camelcase-keys": { "version": "1.0.0", - "from": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-1.0.0.tgz", + "from": "camelcase-keys@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-1.0.0.tgz", "dependencies": { "camelcase": { "version": "1.0.2", - "from": "https://registry.npmjs.org/camelcase/-/camelcase-1.0.2.tgz", + "from": "camelcase@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.0.2.tgz" }, "map-obj": { "version": "1.0.0", - "from": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.0.tgz", + "from": "map-obj@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.0.tgz" } } }, "indent-string": { "version": "1.2.1", - "from": "https://registry.npmjs.org/indent-string/-/indent-string-1.2.1.tgz", + "from": "indent-string@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-1.2.1.tgz", "dependencies": { "repeating": { "version": "1.1.2", - "from": "https://registry.npmjs.org/repeating/-/repeating-1.1.2.tgz", + "from": "repeating@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.2.tgz", "dependencies": { "is-finite": { "version": "1.0.0", - "from": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.0.tgz", + "from": "is-finite@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.0.tgz" } } @@ -6453,13 +6690,13 @@ } }, "minimist": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/minimist/-/minimist-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.0.tgz" + "version": "1.1.1", + "from": "minimist@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.1.tgz" }, "object-assign": { "version": "2.0.0", - "from": "https://registry.npmjs.org/object-assign/-/object-assign-2.0.0.tgz", + "from": "object-assign@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.0.0.tgz" } } @@ -6468,51 +6705,51 @@ }, "lodash._reinterpolate": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", + "from": "lodash._reinterpolate@>=2.4.1 <3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz" }, "lodash.template": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", + "from": "lodash.template@>=2.4.1 <3.0.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", "dependencies": { "lodash.defaults": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", + "from": "lodash.defaults@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } }, "lodash.escape": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", + "from": "lodash.escape@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", "dependencies": { "lodash._escapehtmlchar": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", + "from": "lodash._escapehtmlchar@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", "dependencies": { "lodash._htmlescapes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", + "from": "lodash._htmlescapes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz" } } }, "lodash._reunescapedhtml": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", + "from": "lodash._reunescapedhtml@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", "dependencies": { "lodash._htmlescapes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", + "from": "lodash._htmlescapes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz" } } @@ -6521,39 +6758,39 @@ }, "lodash._escapestringchar": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", + "from": "lodash._escapestringchar@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz" }, "lodash.keys": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "from": "lodash.keys@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "dependencies": { "lodash._isnative": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "from": "lodash._isnative@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" }, "lodash.isobject": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "from": "lodash.isobject@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } }, "lodash._shimkeys": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "from": "lodash._shimkeys@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } @@ -6562,54 +6799,54 @@ }, "lodash.templatesettings": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", + "from": "lodash.templatesettings@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz" }, "lodash.values": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", + "from": "lodash.values@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz" } } }, "minimist": { "version": "0.2.0", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "from": "minimist@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz" }, "multipipe": { "version": "0.1.2", - "from": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "from": "multipipe@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "dependencies": { "duplexer2": { "version": "0.0.2", - "from": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "from": "duplexer2@0.0.2", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "dependencies": { "readable-stream": { "version": "1.1.13", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "from": "readable-stream@>=1.1.9 <1.2.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } @@ -6620,51 +6857,51 @@ }, "through2": { "version": "0.5.1", - "from": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "from": "through2@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", "dependencies": { "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.17 <1.1.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "xtend": { "version": "3.0.0", - "from": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "from": "xtend@>=3.0.0 <3.1.0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz" } } }, "vinyl": { "version": "0.2.3", - "from": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", + "from": "vinyl@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", "dependencies": { "clone-stats": { "version": "0.0.1", - "from": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "from": "clone-stats@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" } } @@ -6673,182 +6910,182 @@ }, "lodash.clone": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-2.4.1.tgz", + "from": "lodash.clone@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-2.4.1.tgz", "dependencies": { "lodash._baseclone": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-2.4.1.tgz", + "from": "lodash._baseclone@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-2.4.1.tgz", "dependencies": { "lodash.assign": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-2.4.1.tgz", + "from": "lodash.assign@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-2.4.1.tgz", "dependencies": { "lodash.keys": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "from": "lodash.keys@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "dependencies": { "lodash._isnative": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "from": "lodash._isnative@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" }, "lodash._shimkeys": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "from": "lodash._shimkeys@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz" } } }, "lodash._objecttypes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } }, "lodash.foreach": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-2.4.1.tgz", + "from": "lodash.foreach@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-2.4.1.tgz" }, "lodash.forown": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.forown/-/lodash.forown-2.4.1.tgz", + "from": "lodash.forown@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.forown/-/lodash.forown-2.4.1.tgz", "dependencies": { "lodash.keys": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "from": "lodash.keys@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "dependencies": { "lodash._isnative": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "from": "lodash._isnative@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" }, "lodash._shimkeys": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "from": "lodash._shimkeys@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz" } } }, "lodash._objecttypes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } }, "lodash._getarray": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._getarray/-/lodash._getarray-2.4.1.tgz", + "from": "lodash._getarray@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._getarray/-/lodash._getarray-2.4.1.tgz", "dependencies": { "lodash._arraypool": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._arraypool/-/lodash._arraypool-2.4.1.tgz", + "from": "lodash._arraypool@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._arraypool/-/lodash._arraypool-2.4.1.tgz" } } }, "lodash.isarray": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-2.4.1.tgz", + "from": "lodash.isarray@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-2.4.1.tgz", "dependencies": { "lodash._isnative": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "from": "lodash._isnative@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" } } }, "lodash.isobject": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "from": "lodash.isobject@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } }, "lodash._releasearray": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._releasearray/-/lodash._releasearray-2.4.1.tgz", + "from": "lodash._releasearray@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._releasearray/-/lodash._releasearray-2.4.1.tgz", "dependencies": { "lodash._arraypool": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._arraypool/-/lodash._arraypool-2.4.1.tgz", + "from": "lodash._arraypool@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._arraypool/-/lodash._arraypool-2.4.1.tgz" }, "lodash._maxpoolsize": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._maxpoolsize/-/lodash._maxpoolsize-2.4.1.tgz", + "from": "lodash._maxpoolsize@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._maxpoolsize/-/lodash._maxpoolsize-2.4.1.tgz" } } }, "lodash._slice": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._slice/-/lodash._slice-2.4.1.tgz", + "from": "lodash._slice@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._slice/-/lodash._slice-2.4.1.tgz" } } }, "lodash._basecreatecallback": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._basecreatecallback/-/lodash._basecreatecallback-2.4.1.tgz", + "from": "lodash._basecreatecallback@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._basecreatecallback/-/lodash._basecreatecallback-2.4.1.tgz", "dependencies": { "lodash.bind": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-2.4.1.tgz", + "from": "lodash.bind@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-2.4.1.tgz", "dependencies": { "lodash._createwrapper": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._createwrapper/-/lodash._createwrapper-2.4.1.tgz", + "from": "lodash._createwrapper@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._createwrapper/-/lodash._createwrapper-2.4.1.tgz", "dependencies": { "lodash._basebind": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._basebind/-/lodash._basebind-2.4.1.tgz", + "from": "lodash._basebind@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._basebind/-/lodash._basebind-2.4.1.tgz", "dependencies": { "lodash._basecreate": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-2.4.1.tgz", + "from": "lodash._basecreate@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-2.4.1.tgz", "dependencies": { "lodash._isnative": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "from": "lodash._isnative@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" }, "lodash.noop": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-2.4.1.tgz", + "from": "lodash.noop@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-2.4.1.tgz" } } }, "lodash.isobject": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "from": "lodash.isobject@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } @@ -6857,34 +7094,34 @@ }, "lodash._basecreatewrapper": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._basecreatewrapper/-/lodash._basecreatewrapper-2.4.1.tgz", + "from": "lodash._basecreatewrapper@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._basecreatewrapper/-/lodash._basecreatewrapper-2.4.1.tgz", "dependencies": { "lodash._basecreate": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-2.4.1.tgz", + "from": "lodash._basecreate@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-2.4.1.tgz", "dependencies": { "lodash._isnative": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "from": "lodash._isnative@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" }, "lodash.noop": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-2.4.1.tgz", + "from": "lodash.noop@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-2.4.1.tgz" } } }, "lodash.isobject": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "from": "lodash.isobject@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } @@ -6893,48 +7130,48 @@ }, "lodash.isfunction": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-2.4.1.tgz", + "from": "lodash.isfunction@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-2.4.1.tgz" } } }, "lodash._slice": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._slice/-/lodash._slice-2.4.1.tgz", + "from": "lodash._slice@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._slice/-/lodash._slice-2.4.1.tgz" } } }, "lodash.identity": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.identity/-/lodash.identity-2.4.1.tgz", + "from": "lodash.identity@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.identity/-/lodash.identity-2.4.1.tgz" }, "lodash._setbinddata": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._setbinddata/-/lodash._setbinddata-2.4.1.tgz", + "from": "lodash._setbinddata@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._setbinddata/-/lodash._setbinddata-2.4.1.tgz", "dependencies": { "lodash._isnative": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "from": "lodash._isnative@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" }, "lodash.noop": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-2.4.1.tgz", + "from": "lodash.noop@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-2.4.1.tgz" } } }, "lodash.support": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash.support/-/lodash.support-2.4.1.tgz", + "from": "lodash.support@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.support/-/lodash.support-2.4.1.tgz", "dependencies": { "lodash._isnative": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "from": "lodash._isnative@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" } } @@ -6946,181 +7183,203 @@ } }, "gulp-rename": { - "version": "1.2.0", - "from": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.0.tgz", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.0.tgz" + "version": "1.2.2", + "from": "gulp-rename@>=1.2.0 <2.0.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz" }, "gulp-sourcemaps": { - "version": "1.3.0", - "from": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.3.0.tgz", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.3.0.tgz", + "version": "1.5.1", + "from": "gulp-sourcemaps@>=1.2.2 <2.0.0", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.5.1.tgz", "dependencies": { + "convert-source-map": { + "version": "1.0.0", + "from": "convert-source-map@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.0.0.tgz" + }, + "graceful-fs": { + "version": "3.0.6", + "from": "graceful-fs@>=3.0.5 <4.0.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.6.tgz" + }, + "strip-bom": { + "version": "1.0.0", + "from": "strip-bom@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "dependencies": { + "first-chunk-stream": { + "version": "1.0.0", + "from": "first-chunk-stream@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz" + }, + "is-utf8": { + "version": "0.2.0", + "from": "is-utf8@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.0.tgz" + } + } + }, "through2": { "version": "0.6.3", - "from": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", + "from": "through2@>=0.6.3 <0.7.0", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", "dependencies": { "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.33-1 <1.1.0-0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "xtend": { "version": "4.0.0", - "from": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz", + "from": "xtend@>=4.0.0 <4.1.0-0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" } } }, "vinyl": { "version": "0.4.6", - "from": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "from": "vinyl@>=0.4.6 <0.5.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", "dependencies": { "clone": { "version": "0.2.0", - "from": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "from": "clone@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz" }, "clone-stats": { "version": "0.0.1", - "from": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "from": "clone-stats@>=0.0.1 <0.0.2", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" } } - }, - "convert-source-map": { - "version": "0.4.1", - "from": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.4.1.tgz", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.4.1.tgz" } } }, "gulp-uglify": { "version": "1.1.0", - "from": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-1.1.0.tgz", + "from": "gulp-uglify@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-1.1.0.tgz", "dependencies": { "deepmerge": { "version": "0.2.7", - "from": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.7.tgz", + "from": "deepmerge@>=0.2.7 <0.3.0-0", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.7.tgz" }, "through2": { "version": "0.6.3", - "from": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", + "from": "through2@>=0.6.1 <1.0.0-0", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", "dependencies": { "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.33-1 <1.1.0-0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "xtend": { "version": "4.0.0", - "from": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz", + "from": "xtend@>=4.0.0 <4.1.0-0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" } } }, "uglify-js": { "version": "2.4.16", - "from": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.16.tgz", + "from": "uglify-js@2.4.16", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.16.tgz", "dependencies": { "async": { "version": "0.2.10", - "from": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "from": "async@>=0.2.6 <0.3.0", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "source-map": { "version": "0.1.34", - "from": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz", + "from": "source-map@0.1.34", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", + "from": "amdefine@>=0.0.4", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } }, "optimist": { "version": "0.3.7", - "from": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "from": "optimist@>=0.3.5 <0.4.0", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", "dependencies": { "wordwrap": { "version": "0.0.2", - "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "from": "wordwrap@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" } } }, "uglify-to-browserify": { "version": "1.0.2", - "from": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "from": "uglify-to-browserify@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz" } } }, "vinyl-sourcemaps-apply": { "version": "0.1.4", - "from": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.1.4.tgz", + "from": "vinyl-sourcemaps-apply@>=0.1.1 <0.2.0-0", "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.1.4.tgz", "dependencies": { "source-map": { "version": "0.1.43", - "from": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "from": "source-map@>=0.1.39 <0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", + "from": "amdefine@>=0.0.4", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } @@ -7130,116 +7389,121 @@ } }, "gulp-util": { - "version": "3.0.3", - "from": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.3.tgz", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.3.tgz", + "version": "3.0.4", + "from": "gulp-util@>=3.0.1 <4.0.0", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.4.tgz", "dependencies": { "array-differ": { "version": "1.0.0", - "from": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "from": "array-differ@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz" }, "array-uniq": { "version": "1.0.2", - "from": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz", + "from": "array-uniq@>=1.0.2 <2.0.0", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz" }, "beeper": { "version": "1.0.0", - "from": "https://registry.npmjs.org/beeper/-/beeper-1.0.0.tgz", + "from": "beeper@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.0.0.tgz" }, "chalk": { - "version": "0.5.1", - "from": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "version": "1.0.0", + "from": "chalk@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.0.0.tgz", "dependencies": { "ansi-styles": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" + "version": "2.0.1", + "from": "ansi-styles@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.0.1.tgz" }, "escape-string-regexp": { - "version": "1.0.2", - "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz" + "version": "1.0.3", + "from": "escape-string-regexp@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz" }, "has-ansi": { - "version": "0.1.0", - "from": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "version": "1.0.3", + "from": "has-ansi@>=1.0.3 <2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-1.0.3.tgz", "dependencies": { "ansi-regex": { - "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" + "version": "1.1.1", + "from": "ansi-regex@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz" + }, + "get-stdin": { + "version": "4.0.1", + "from": "get-stdin@>=4.0.1 <5.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" } } }, "strip-ansi": { - "version": "0.3.0", - "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "version": "2.0.1", + "from": "strip-ansi@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", "dependencies": { "ansi-regex": { - "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" + "version": "1.1.1", + "from": "ansi-regex@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz" } } }, "supports-color": { - "version": "0.2.0", - "from": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" + "version": "1.3.1", + "from": "supports-color@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz" } } }, "dateformat": { "version": "1.0.11", - "from": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.11.tgz", + "from": "dateformat@>=1.0.11 <2.0.0", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.11.tgz", "dependencies": { "get-stdin": { "version": "4.0.1", - "from": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "from": "get-stdin@*", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" }, "meow": { - "version": "3.0.0", - "from": "https://registry.npmjs.org/meow/-/meow-3.0.0.tgz", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.0.0.tgz", + "version": "3.1.0", + "from": "meow@*", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.1.0.tgz", "dependencies": { "camelcase-keys": { "version": "1.0.0", - "from": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-1.0.0.tgz", + "from": "camelcase-keys@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-1.0.0.tgz", "dependencies": { "camelcase": { "version": "1.0.2", - "from": "https://registry.npmjs.org/camelcase/-/camelcase-1.0.2.tgz", + "from": "camelcase@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.0.2.tgz" }, "map-obj": { "version": "1.0.0", - "from": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.0.tgz", + "from": "map-obj@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.0.tgz" } } }, "indent-string": { "version": "1.2.1", - "from": "https://registry.npmjs.org/indent-string/-/indent-string-1.2.1.tgz", + "from": "indent-string@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-1.2.1.tgz", "dependencies": { "repeating": { "version": "1.1.2", - "from": "https://registry.npmjs.org/repeating/-/repeating-1.1.2.tgz", + "from": "repeating@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.2.tgz", "dependencies": { "is-finite": { "version": "1.0.0", - "from": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.0.tgz", + "from": "is-finite@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.0.tgz" } } @@ -7250,144 +7514,123 @@ } } }, - "lodash.reescape": { - "version": "3.0.1", - "from": "https://registry.npmjs.org/lodash.reescape/-/lodash.reescape-3.0.1.tgz", - "resolved": "https://registry.npmjs.org/lodash.reescape/-/lodash.reescape-3.0.1.tgz", - "dependencies": { - "lodash._reescape": { - "version": "3.0.0", - "from": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz" - } - } + "lodash._reescape": { + "version": "3.0.0", + "from": "lodash._reescape@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz" }, - "lodash.reevaluate": { - "version": "3.0.1", - "from": "https://registry.npmjs.org/lodash.reevaluate/-/lodash.reevaluate-3.0.1.tgz", - "resolved": "https://registry.npmjs.org/lodash.reevaluate/-/lodash.reevaluate-3.0.1.tgz", - "dependencies": { - "lodash._reevaluate": { - "version": "3.0.0", - "from": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz" - } - } + "lodash._reevaluate": { + "version": "3.0.0", + "from": "lodash._reevaluate@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz" }, - "lodash.reinterpolate": { - "version": "3.0.1", - "from": "https://registry.npmjs.org/lodash.reinterpolate/-/lodash.reinterpolate-3.0.1.tgz", - "resolved": "https://registry.npmjs.org/lodash.reinterpolate/-/lodash.reinterpolate-3.0.1.tgz", - "dependencies": { - "lodash._reinterpolate": { - "version": "3.0.0", - "from": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz" - } - } + "lodash._reinterpolate": { + "version": "3.0.0", + "from": "lodash._reinterpolate@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz" }, "lodash.template": { - "version": "3.3.0", - "from": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.3.0.tgz", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.3.0.tgz", + "version": "3.4.0", + "from": "lodash.template@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.4.0.tgz", "dependencies": { "lodash._basecopy": { "version": "3.0.0", - "from": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.0.tgz", + "from": "lodash._basecopy@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.0.tgz" }, "lodash._basetostring": { "version": "3.0.0", - "from": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.0.tgz", + "from": "lodash._basetostring@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.0.tgz" }, "lodash._basevalues": { "version": "3.0.0", - "from": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "from": "lodash._basevalues@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz" }, "lodash._isiterateecall": { - "version": "3.0.2", - "from": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.2.tgz", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.2.tgz" - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "from": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz" + "version": "3.0.5", + "from": "lodash._isiterateecall@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.5.tgz" }, "lodash.escape": { "version": "3.0.0", - "from": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.0.0.tgz", + "from": "lodash.escape@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.0.0.tgz" }, "lodash.keys": { - "version": "3.0.3", - "from": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.0.3.tgz", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.0.3.tgz", + "version": "3.0.5", + "from": "lodash.keys@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.0.5.tgz", "dependencies": { "lodash.isarguments": { - "version": "3.0.0", - "from": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.0.0.tgz", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.0.0.tgz" + "version": "3.0.1", + "from": "lodash.isarguments@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.0.1.tgz" }, "lodash.isarray": { - "version": "3.0.0", - "from": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.0.tgz", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.0.tgz" + "version": "3.0.1", + "from": "lodash.isarray@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.1.tgz" }, "lodash.isnative": { - "version": "3.0.0", - "from": "https://registry.npmjs.org/lodash.isnative/-/lodash.isnative-3.0.0.tgz", - "resolved": "https://registry.npmjs.org/lodash.isnative/-/lodash.isnative-3.0.0.tgz" + "version": "3.0.1", + "from": "lodash.isnative@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isnative/-/lodash.isnative-3.0.1.tgz" } } }, + "lodash.restparam": { + "version": "3.6.0", + "from": "lodash.restparam@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.0.tgz" + }, "lodash.templatesettings": { "version": "3.1.0", - "from": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.0.tgz", + "from": "lodash.templatesettings@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.0.tgz" } } }, "minimist": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/minimist/-/minimist-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.0.tgz" + "version": "1.1.1", + "from": "minimist@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.1.tgz" }, "multipipe": { "version": "0.1.2", - "from": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "from": "multipipe@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "dependencies": { "duplexer2": { "version": "0.0.2", - "from": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "from": "duplexer2@0.0.2", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "dependencies": { "readable-stream": { "version": "1.1.13", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "from": "readable-stream@>=1.1.9 <1.2.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } @@ -7398,66 +7641,66 @@ }, "object-assign": { "version": "2.0.0", - "from": "https://registry.npmjs.org/object-assign/-/object-assign-2.0.0.tgz", + "from": "object-assign@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.0.0.tgz" }, "replace-ext": { "version": "0.0.1", - "from": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "from": "replace-ext@0.0.1", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" }, "through2": { "version": "0.6.3", - "from": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", + "from": "through2@>=0.6.1 <1.0.0-0", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", "dependencies": { "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.33-1 <1.1.0-0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "xtend": { "version": "4.0.0", - "from": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz", + "from": "xtend@>=4.0.0 <4.1.0-0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" } } }, "vinyl": { "version": "0.4.6", - "from": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "from": "vinyl@>=0.4.6 <0.5.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", "dependencies": { "clone": { "version": "0.2.0", - "from": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "from": "clone@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz" }, "clone-stats": { "version": "0.0.1", - "from": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "from": "clone-stats@>=0.0.1 <0.0.2", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" } } @@ -7466,91 +7709,91 @@ }, "jasmine-node": { "version": "1.14.5", - "from": "https://registry.npmjs.org/jasmine-node/-/jasmine-node-1.14.5.tgz", + "from": "jasmine-node@>=1.14.5 <1.15.0", "resolved": "https://registry.npmjs.org/jasmine-node/-/jasmine-node-1.14.5.tgz", "dependencies": { "coffee-script": { "version": "1.9.1", - "from": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.9.1.tgz", + "from": "coffee-script@>=1.0.1", "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.9.1.tgz" }, "jasmine-growl-reporter": { "version": "0.0.3", - "from": "https://registry.npmjs.org/jasmine-growl-reporter/-/jasmine-growl-reporter-0.0.3.tgz", + "from": "jasmine-growl-reporter@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/jasmine-growl-reporter/-/jasmine-growl-reporter-0.0.3.tgz", "dependencies": { "growl": { "version": "1.7.0", - "from": "https://registry.npmjs.org/growl/-/growl-1.7.0.tgz", + "from": "growl@>=1.7.0 <1.8.0", "resolved": "https://registry.npmjs.org/growl/-/growl-1.7.0.tgz" } } }, "requirejs": { - "version": "2.1.16", - "from": "https://registry.npmjs.org/requirejs/-/requirejs-2.1.16.tgz", - "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.1.16.tgz" + "version": "2.1.17", + "from": "requirejs@>=0.27.1", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.1.17.tgz" }, "walkdir": { "version": "0.0.7", - "from": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.7.tgz", + "from": "walkdir@>=0.0.1", "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.7.tgz" }, "underscore": { - "version": "1.8.1", - "from": "https://registry.npmjs.org/underscore/-/underscore-1.8.1.tgz", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.1.tgz" + "version": "1.8.3", + "from": "underscore@>=1.3.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz" }, "gaze": { "version": "0.3.4", - "from": "https://registry.npmjs.org/gaze/-/gaze-0.3.4.tgz", + "from": "gaze@>=0.3.2 <0.4.0", "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.3.4.tgz", "dependencies": { "minimatch": { "version": "0.2.14", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "from": "minimatch@>=0.2.9 <0.3.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "fileset": { "version": "0.1.5", - "from": "https://registry.npmjs.org/fileset/-/fileset-0.1.5.tgz", + "from": "fileset@>=0.1.5 <0.2.0", "resolved": "https://registry.npmjs.org/fileset/-/fileset-0.1.5.tgz", "dependencies": { "glob": { "version": "3.2.11", - "from": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "from": "glob@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "from": "minimatch@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -7563,93 +7806,98 @@ }, "mkdirp": { "version": "0.3.5", - "from": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "from": "mkdirp@>=0.3.5 <0.4.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" } } }, "jasmine-reporters": { "version": "1.0.1", - "from": "https://registry.npmjs.org/jasmine-reporters/-/jasmine-reporters-1.0.1.tgz", + "from": "jasmine-reporters@>=1.0.1 <1.1.0", "resolved": "https://registry.npmjs.org/jasmine-reporters/-/jasmine-reporters-1.0.1.tgz", "dependencies": { "mkdirp": { "version": "0.3.5", - "from": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "from": "mkdirp@>=0.3.5 <0.4.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" } } }, "jshint-stylish": { - "version": "1.0.0", - "from": "https://registry.npmjs.org/jshint-stylish/-/jshint-stylish-1.0.0.tgz", - "resolved": "https://registry.npmjs.org/jshint-stylish/-/jshint-stylish-1.0.0.tgz", + "version": "1.0.1", + "from": "jshint-stylish@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/jshint-stylish/-/jshint-stylish-1.0.1.tgz", "dependencies": { "chalk": { - "version": "0.5.1", - "from": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "version": "1.0.0", + "from": "chalk@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.0.0.tgz", "dependencies": { "ansi-styles": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" + "version": "2.0.1", + "from": "ansi-styles@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.0.1.tgz" }, "escape-string-regexp": { - "version": "1.0.2", - "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz" + "version": "1.0.3", + "from": "escape-string-regexp@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.3.tgz" }, "has-ansi": { - "version": "0.1.0", - "from": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "version": "1.0.3", + "from": "has-ansi@>=1.0.3 <2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-1.0.3.tgz", "dependencies": { "ansi-regex": { - "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" + "version": "1.1.1", + "from": "ansi-regex@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz" + }, + "get-stdin": { + "version": "4.0.1", + "from": "get-stdin@>=4.0.1 <5.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" } } }, "strip-ansi": { - "version": "0.3.0", - "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "version": "2.0.1", + "from": "strip-ansi@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", "dependencies": { "ansi-regex": { - "version": "0.2.1", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" + "version": "1.1.1", + "from": "ansi-regex@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz" } } }, "supports-color": { - "version": "0.2.0", - "from": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" + "version": "1.3.1", + "from": "supports-color@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz" } } }, "log-symbols": { - "version": "1.0.1", - "from": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.1.tgz", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.1.tgz" + "version": "1.0.2", + "from": "log-symbols@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz" }, "string-length": { "version": "1.0.0", - "from": "https://registry.npmjs.org/string-length/-/string-length-1.0.0.tgz", + "from": "string-length@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.0.tgz", "dependencies": { "strip-ansi": { "version": "2.0.1", - "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", + "from": "strip-ansi@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", "dependencies": { "ansi-regex": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.0.tgz" + "version": "1.1.1", + "from": "ansi-regex@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz" } } } @@ -7657,7 +7905,7 @@ }, "text-table": { "version": "0.2.0", - "from": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "from": "text-table@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" } } @@ -7669,149 +7917,149 @@ "dependencies": { "di": { "version": "0.0.1", - "from": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "from": "di@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz" }, "socket.io": { - "version": "1.3.4", - "from": "https://registry.npmjs.org/socket.io/-/socket.io-1.3.4.tgz", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-1.3.4.tgz", + "version": "1.3.5", + "from": "socket.io@>=1.3.0 <1.4.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-1.3.5.tgz", "dependencies": { "engine.io": { "version": "1.5.1", - "from": "https://registry.npmjs.org/engine.io/-/engine.io-1.5.1.tgz", + "from": "engine.io@1.5.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.5.1.tgz", "dependencies": { "debug": { "version": "1.0.3", - "from": "https://registry.npmjs.org/debug/-/debug-1.0.3.tgz", + "from": "debug@1.0.3", "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.3.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "from": "ms@0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } }, "ws": { "version": "0.5.0", - "from": "https://registry.npmjs.org/ws/-/ws-0.5.0.tgz", + "from": "ws@0.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-0.5.0.tgz", "dependencies": { "nan": { "version": "1.4.3", - "from": "https://registry.npmjs.org/nan/-/nan-1.4.3.tgz", + "from": "nan@>=1.4.0 <1.5.0", "resolved": "https://registry.npmjs.org/nan/-/nan-1.4.3.tgz" }, "options": { "version": "0.0.6", - "from": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "from": "options@>=0.0.5", "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz" }, "ultron": { "version": "1.0.1", - "from": "https://registry.npmjs.org/ultron/-/ultron-1.0.1.tgz", + "from": "ultron@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.1.tgz" } } }, "engine.io-parser": { "version": "1.2.1", - "from": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.2.1.tgz", + "from": "engine.io-parser@1.2.1", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.2.1.tgz", "dependencies": { "after": { "version": "0.8.1", - "from": "https://registry.npmjs.org/after/-/after-0.8.1.tgz", + "from": "after@0.8.1", "resolved": "https://registry.npmjs.org/after/-/after-0.8.1.tgz" }, "arraybuffer.slice": { "version": "0.0.6", - "from": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz", + "from": "arraybuffer.slice@0.0.6", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz" }, "base64-arraybuffer": { "version": "0.1.2", - "from": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.2.tgz", + "from": "base64-arraybuffer@0.1.2", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.2.tgz" }, "blob": { "version": "0.0.2", - "from": "https://registry.npmjs.org/blob/-/blob-0.0.2.tgz", + "from": "blob@0.0.2", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.2.tgz" }, "has-binary": { "version": "0.1.5", - "from": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.5.tgz", + "from": "has-binary@0.1.5", "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.5.tgz", "dependencies": { "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" } } }, "utf8": { "version": "2.0.0", - "from": "https://registry.npmjs.org/utf8/-/utf8-2.0.0.tgz", + "from": "utf8@2.0.0", "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.0.0.tgz" } } }, "base64id": { "version": "0.1.0", - "from": "https://registry.npmjs.org/base64id/-/base64id-0.1.0.tgz", + "from": "base64id@0.1.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-0.1.0.tgz" } } }, "socket.io-parser": { - "version": "2.2.3", - "from": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.3.tgz", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.3.tgz", + "version": "2.2.4", + "from": "socket.io-parser@2.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.4.tgz", "dependencies": { "debug": { "version": "0.7.4", - "from": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "from": "debug@0.7.4", "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" }, "json3": { "version": "3.2.6", - "from": "https://registry.npmjs.org/json3/-/json3-3.2.6.tgz", + "from": "json3@3.2.6", "resolved": "https://registry.npmjs.org/json3/-/json3-3.2.6.tgz" }, "component-emitter": { "version": "1.1.2", - "from": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", + "from": "component-emitter@1.1.2", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" } } }, "socket.io-client": { - "version": "1.3.4", - "from": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.3.4.tgz", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.3.4.tgz", + "version": "1.3.5", + "from": "socket.io-client@1.3.5", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.3.5.tgz", "dependencies": { "debug": { "version": "0.7.4", - "from": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "from": "debug@0.7.4", "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" }, "engine.io-client": { "version": "1.5.1", - "from": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.5.1.tgz", + "from": "engine.io-client@1.5.1", "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.5.1.tgz", "dependencies": { "has-cors": { "version": "1.0.3", - "from": "https://registry.npmjs.org/has-cors/-/has-cors-1.0.3.tgz", + "from": "has-cors@1.0.3", "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.0.3.tgz", "dependencies": { "global": { @@ -7823,27 +8071,27 @@ }, "ws": { "version": "0.4.31", - "from": "https://registry.npmjs.org/ws/-/ws-0.4.31.tgz", + "from": "ws@0.4.31", "resolved": "https://registry.npmjs.org/ws/-/ws-0.4.31.tgz", "dependencies": { "commander": { "version": "0.6.1", - "from": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "from": "commander@>=0.6.1 <0.7.0", "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz" }, "nan": { "version": "0.3.2", - "from": "https://registry.npmjs.org/nan/-/nan-0.3.2.tgz", + "from": "nan@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/nan/-/nan-0.3.2.tgz" }, "tinycolor": { "version": "0.0.1", - "from": "https://registry.npmjs.org/tinycolor/-/tinycolor-0.0.1.tgz", + "from": "tinycolor@>=0.0.0 <1.0.0", "resolved": "https://registry.npmjs.org/tinycolor/-/tinycolor-0.0.1.tgz" }, "options": { "version": "0.0.6", - "from": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "from": "options@>=0.0.5", "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz" } } @@ -7855,73 +8103,73 @@ }, "engine.io-parser": { "version": "1.2.1", - "from": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.2.1.tgz", + "from": "engine.io-parser@1.2.1", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.2.1.tgz", "dependencies": { "after": { "version": "0.8.1", - "from": "https://registry.npmjs.org/after/-/after-0.8.1.tgz", + "from": "after@0.8.1", "resolved": "https://registry.npmjs.org/after/-/after-0.8.1.tgz" }, "arraybuffer.slice": { "version": "0.0.6", - "from": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz", + "from": "arraybuffer.slice@0.0.6", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz" }, "base64-arraybuffer": { "version": "0.1.2", - "from": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.2.tgz", + "from": "base64-arraybuffer@0.1.2", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.2.tgz" }, "blob": { "version": "0.0.2", - "from": "https://registry.npmjs.org/blob/-/blob-0.0.2.tgz", + "from": "blob@0.0.2", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.2.tgz" }, "has-binary": { "version": "0.1.5", - "from": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.5.tgz", + "from": "has-binary@0.1.5", "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.5.tgz", "dependencies": { "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" } } }, "utf8": { "version": "2.0.0", - "from": "https://registry.npmjs.org/utf8/-/utf8-2.0.0.tgz", + "from": "utf8@2.0.0", "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.0.0.tgz" } } }, "debug": { "version": "1.0.4", - "from": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz", + "from": "debug@1.0.4", "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "from": "ms@0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } }, "parseuri": { "version": "0.0.4", - "from": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.4.tgz", + "from": "parseuri@0.0.4", "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.4.tgz", "dependencies": { "better-assert": { "version": "1.0.2", - "from": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "from": "better-assert@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "dependencies": { "callsite": { "version": "1.0.0", - "from": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "from": "callsite@1.0.0", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz" } } @@ -7930,17 +8178,17 @@ }, "parsejson": { "version": "0.0.1", - "from": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.1.tgz", + "from": "parsejson@0.0.1", "resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.1.tgz", "dependencies": { "better-assert": { "version": "1.0.2", - "from": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "from": "better-assert@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "dependencies": { "callsite": { "version": "1.0.0", - "from": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "from": "callsite@1.0.0", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz" } } @@ -7949,17 +8197,17 @@ }, "parseqs": { "version": "0.0.2", - "from": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.2.tgz", + "from": "parseqs@0.0.2", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.2.tgz", "dependencies": { "better-assert": { "version": "1.0.2", - "from": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "from": "better-assert@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "dependencies": { "callsite": { "version": "1.0.0", - "from": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "from": "callsite@1.0.0", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz" } } @@ -7968,56 +8216,56 @@ }, "component-inherit": { "version": "0.0.3", - "from": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "from": "component-inherit@0.0.3", "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz" } } }, "component-bind": { "version": "1.0.0", - "from": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "from": "component-bind@1.0.0", "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz" }, "component-emitter": { "version": "1.1.2", - "from": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", + "from": "component-emitter@1.1.2", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz" }, "object-component": { "version": "0.0.3", - "from": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "from": "object-component@0.0.3", "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz" }, "has-binary": { "version": "0.1.6", - "from": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.6.tgz", + "from": "has-binary@0.1.6", "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.6.tgz", "dependencies": { "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" } } }, "indexof": { "version": "0.0.1", - "from": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "from": "indexof@0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz" }, "parseuri": { "version": "0.0.2", - "from": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.2.tgz", + "from": "parseuri@0.0.2", "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.2.tgz", "dependencies": { "better-assert": { "version": "1.0.2", - "from": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "from": "better-assert@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", "dependencies": { "callsite": { "version": "1.0.0", - "from": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "from": "callsite@1.0.0", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz" } } @@ -8026,87 +8274,87 @@ }, "to-array": { "version": "0.1.3", - "from": "https://registry.npmjs.org/to-array/-/to-array-0.1.3.tgz", + "from": "to-array@0.1.3", "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.3.tgz" }, "backo2": { "version": "1.0.2", - "from": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "from": "backo2@1.0.2", "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz" } } }, "socket.io-adapter": { "version": "0.3.1", - "from": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.3.1.tgz", + "from": "socket.io-adapter@0.3.1", "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.3.1.tgz", "dependencies": { "debug": { "version": "1.0.2", - "from": "https://registry.npmjs.org/debug/-/debug-1.0.2.tgz", + "from": "debug@1.0.2", "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.2.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "from": "ms@0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } }, "socket.io-parser": { "version": "2.2.2", - "from": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.2.tgz", + "from": "socket.io-parser@2.2.2", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.2.tgz", "dependencies": { "debug": { "version": "0.7.4", - "from": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "from": "debug@0.7.4", "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" }, "json3": { "version": "3.2.6", - "from": "https://registry.npmjs.org/json3/-/json3-3.2.6.tgz", + "from": "json3@3.2.6", "resolved": "https://registry.npmjs.org/json3/-/json3-3.2.6.tgz" }, "component-emitter": { "version": "1.1.2", - "from": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", + "from": "component-emitter@1.1.2", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" } } }, "object-keys": { "version": "1.0.1", - "from": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.1.tgz", + "from": "object-keys@1.0.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.1.tgz" } } }, "has-binary-data": { "version": "0.1.3", - "from": "https://registry.npmjs.org/has-binary-data/-/has-binary-data-0.1.3.tgz", + "from": "has-binary-data@0.1.3", "resolved": "https://registry.npmjs.org/has-binary-data/-/has-binary-data-0.1.3.tgz", "dependencies": { "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" } } }, "debug": { "version": "2.1.0", - "from": "https://registry.npmjs.org/debug/-/debug-2.1.0.tgz", + "from": "debug@2.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-2.1.0.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "from": "ms@0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } @@ -8114,105 +8362,57 @@ } }, "chokidar": { - "version": "1.0.0-rc3", - "from": "https://registry.npmjs.org/chokidar/-/chokidar-1.0.0-rc3.tgz", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.0.0-rc3.tgz", + "version": "0.12.6", + "from": "chokidar@>=0.8.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-0.12.6.tgz", "dependencies": { - "anymatch": { - "version": "1.1.0", - "from": "https://registry.npmjs.org/anymatch/-/anymatch-1.1.0.tgz", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.1.0.tgz", - "dependencies": { - "minimatch": { - "version": "1.0.0", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", - "dependencies": { - "lru-cache": { - "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" - }, - "sigmund": { - "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" - } - } - } - } - }, - "async-each": { - "version": "0.1.6", - "from": "https://registry.npmjs.org/async-each/-/async-each-0.1.6.tgz", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-0.1.6.tgz" - }, - "glob-parent": { - "version": "1.0.0", - "from": "https://registry.npmjs.org/glob-parent/-/glob-parent-1.0.0.tgz", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-1.0.0.tgz", - "dependencies": { - "is-glob": { - "version": "0.3.0", - "from": "https://registry.npmjs.org/is-glob/-/is-glob-0.3.0.tgz", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-0.3.0.tgz" - } - } - }, - "is-binary-path": { - "version": "1.0.0", - "from": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.0.tgz", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.0.tgz", - "dependencies": { - "binary-extensions": { - "version": "1.3.0", - "from": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.3.0.tgz", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.3.0.tgz" - } - } - }, "readdirp": { "version": "1.3.0", - "from": "https://registry.npmjs.org/readdirp/-/readdirp-1.3.0.tgz", + "from": "readdirp@>=1.3.0 <1.4.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-1.3.0.tgz", "dependencies": { "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.26-2 <1.1.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } } } }, + "async-each": { + "version": "0.1.6", + "from": "async-each@>=0.1.5 <0.2.0", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-0.1.6.tgz" + }, "fsevents": { "version": "0.3.5", - "from": "https://registry.npmjs.org/fsevents/-/fsevents-0.3.5.tgz", + "from": "fsevents@>=0.3.1 <0.4.0", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-0.3.5.tgz", "dependencies": { "nan": { "version": "1.5.3", - "from": "https://registry.npmjs.org/nan/-/nan-1.5.3.tgz", + "from": "nan@>=1.5.0 <1.6.0", "resolved": "https://registry.npmjs.org/nan/-/nan-1.5.3.tgz" } } @@ -8221,27 +8421,27 @@ }, "glob": { "version": "3.2.11", - "from": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "from": "glob@>=3.2.7 <3.3.0", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "from": "minimatch@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -8250,54 +8450,54 @@ }, "minimatch": { "version": "0.2.14", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "from": "minimatch@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "expand-braces": { "version": "0.1.1", - "from": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.1.tgz", + "from": "expand-braces@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.1.tgz", "dependencies": { "array-slice": { "version": "0.2.2", - "from": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.2.tgz", + "from": "array-slice@>=0.2.2 <0.3.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.2.tgz" }, "array-uniq": { "version": "1.0.2", - "from": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz", + "from": "array-uniq@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz" }, "braces": { "version": "0.1.5", - "from": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", + "from": "braces@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", "dependencies": { "expand-range": { "version": "0.1.1", - "from": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "from": "expand-range@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", "dependencies": { "is-number": { "version": "0.1.1", - "from": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "from": "is-number@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz" }, "repeat-string": { "version": "0.2.2", - "from": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", + "from": "repeat-string@>=0.2.2 <0.3.0", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz" } } @@ -8308,49 +8508,49 @@ }, "http-proxy": { "version": "0.10.4", - "from": "https://registry.npmjs.org/http-proxy/-/http-proxy-0.10.4.tgz", + "from": "http-proxy@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-0.10.4.tgz", "dependencies": { "pkginfo": { "version": "0.3.0", - "from": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.0.tgz", + "from": "pkginfo@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.0.tgz" }, "utile": { "version": "0.2.1", - "from": "https://registry.npmjs.org/utile/-/utile-0.2.1.tgz", + "from": "utile@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/utile/-/utile-0.2.1.tgz", "dependencies": { "async": { "version": "0.2.10", - "from": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "from": "async@>=0.2.9 <0.3.0", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "deep-equal": { "version": "1.0.0", - "from": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.0.tgz", + "from": "deep-equal@*", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.0.tgz" }, "i": { - "version": "0.3.2", - "from": "https://registry.npmjs.org/i/-/i-0.3.2.tgz", - "resolved": "https://registry.npmjs.org/i/-/i-0.3.2.tgz" + "version": "0.3.3", + "from": "i@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/i/-/i-0.3.3.tgz" }, "mkdirp": { "version": "0.5.0", - "from": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "from": "mkdirp@>=0.0.0 <1.0.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "from": "minimist@0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "ncp": { "version": "0.4.2", - "from": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", + "from": "ncp@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz" } } @@ -8359,261 +8559,261 @@ }, "optimist": { "version": "0.6.1", - "from": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "from": "optimist@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "dependencies": { "wordwrap": { "version": "0.0.2", - "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "from": "wordwrap@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" }, "minimist": { "version": "0.0.10", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "from": "minimist@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } }, "rimraf": { "version": "2.2.8", - "from": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "from": "rimraf@>=2.2.5 <2.3.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" }, "q": { "version": "0.9.7", - "from": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "from": "q@>=0.9.7 <0.10.0", "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz" }, "colors": { "version": "0.6.2", - "from": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "from": "colors@>=0.6.2 <0.7.0", "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz" }, "mime": { "version": "1.2.11", - "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "from": "mime@>=1.2.11 <1.3.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "log4js": { "version": "0.6.22", - "from": "https://registry.npmjs.org/log4js/-/log4js-0.6.22.tgz", + "from": "log4js@>=0.6.3 <0.7.0", "resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.22.tgz", "dependencies": { "async": { "version": "0.2.10", - "from": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "from": "async@>=0.2.9 <0.3.0", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.2 <1.1.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "semver": { "version": "1.1.4", - "from": "https://registry.npmjs.org/semver/-/semver-1.1.4.tgz", + "from": "semver@>=1.1.4 <1.2.0", "resolved": "https://registry.npmjs.org/semver/-/semver-1.1.4.tgz" } } }, "useragent": { "version": "2.0.10", - "from": "https://registry.npmjs.org/useragent/-/useragent-2.0.10.tgz", + "from": "useragent@>=2.0.4 <2.1.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.0.10.tgz", "dependencies": { "lru-cache": { "version": "2.2.4", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", + "from": "lru-cache@>=2.2.0 <2.3.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz" } } }, "graceful-fs": { "version": "2.0.3", - "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "from": "graceful-fs@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz" }, "connect": { "version": "2.26.6", - "from": "https://registry.npmjs.org/connect/-/connect-2.26.6.tgz", + "from": "connect@>=2.26.0 <2.27.0", "resolved": "https://registry.npmjs.org/connect/-/connect-2.26.6.tgz", "dependencies": { "basic-auth-connect": { "version": "1.0.0", - "from": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", + "from": "basic-auth-connect@1.0.0", "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz" }, "body-parser": { "version": "1.8.4", - "from": "https://registry.npmjs.org/body-parser/-/body-parser-1.8.4.tgz", + "from": "body-parser@>=1.8.4 <1.9.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.8.4.tgz", "dependencies": { "iconv-lite": { "version": "0.4.4", - "from": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.4.tgz", + "from": "iconv-lite@0.4.4", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.4.tgz" }, "on-finished": { "version": "2.1.0", - "from": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", + "from": "on-finished@2.1.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", "dependencies": { "ee-first": { "version": "1.0.5", - "from": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz", + "from": "ee-first@1.0.5", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz" } } }, "raw-body": { "version": "1.3.0", - "from": "https://registry.npmjs.org/raw-body/-/raw-body-1.3.0.tgz", + "from": "raw-body@1.3.0", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.3.0.tgz" } } }, "bytes": { "version": "1.0.0", - "from": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", + "from": "bytes@1.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz" }, "cookie": { "version": "0.1.2", - "from": "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz", + "from": "cookie@0.1.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz" }, "cookie-parser": { "version": "1.3.4", - "from": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.4.tgz", + "from": "cookie-parser@>=1.3.3 <1.4.0", "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.4.tgz", "dependencies": { "cookie-signature": { "version": "1.0.6", - "from": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "from": "cookie-signature@1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" } } }, "cookie-signature": { "version": "1.0.5", - "from": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.5.tgz", + "from": "cookie-signature@1.0.5", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.5.tgz" }, "compression": { "version": "1.1.2", - "from": "https://registry.npmjs.org/compression/-/compression-1.1.2.tgz", + "from": "compression@>=1.1.2 <1.2.0", "resolved": "https://registry.npmjs.org/compression/-/compression-1.1.2.tgz", "dependencies": { "accepts": { "version": "1.1.4", - "from": "https://registry.npmjs.org/accepts/-/accepts-1.1.4.tgz", + "from": "accepts@>=1.1.3 <1.2.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.1.4.tgz", "dependencies": { "mime-types": { - "version": "2.0.9", - "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", + "version": "2.0.10", + "from": "mime-types@>=2.0.4 <2.1.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.10.tgz", "dependencies": { "mime-db": { - "version": "1.7.0", - "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz" + "version": "1.8.0", + "from": "mime-db@>=1.8.0 <1.9.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.8.0.tgz" } } }, "negotiator": { "version": "0.4.9", - "from": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz", + "from": "negotiator@0.4.9", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz" } } }, "compressible": { "version": "2.0.2", - "from": "https://registry.npmjs.org/compressible/-/compressible-2.0.2.tgz", + "from": "compressible@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.2.tgz", "dependencies": { "mime-db": { - "version": "1.7.0", - "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz" + "version": "1.8.0", + "from": "mime-db@>=1.8.0 <1.9.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.8.0.tgz" } } }, "vary": { "version": "1.0.0", - "from": "https://registry.npmjs.org/vary/-/vary-1.0.0.tgz", + "from": "vary@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.0.tgz" } } }, "connect-timeout": { "version": "1.3.0", - "from": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.3.0.tgz", + "from": "connect-timeout@>=1.3.0 <1.4.0", "resolved": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.3.0.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "from": "ms@0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } }, "csurf": { "version": "1.6.6", - "from": "https://registry.npmjs.org/csurf/-/csurf-1.6.6.tgz", + "from": "csurf@>=1.6.2 <1.7.0", "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.6.6.tgz", "dependencies": { "csrf": { "version": "2.0.6", - "from": "https://registry.npmjs.org/csrf/-/csrf-2.0.6.tgz", + "from": "csrf@>=2.0.5 <2.1.0", "resolved": "https://registry.npmjs.org/csrf/-/csrf-2.0.6.tgz", "dependencies": { "base64-url": { "version": "1.2.1", - "from": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", + "from": "base64-url@1.2.1", "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz" }, "rndm": { "version": "1.1.0", - "from": "https://registry.npmjs.org/rndm/-/rndm-1.1.0.tgz", + "from": "rndm@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.1.0.tgz" }, "scmp": { "version": "1.0.0", - "from": "https://registry.npmjs.org/scmp/-/scmp-1.0.0.tgz", + "from": "scmp@1.0.0", "resolved": "https://registry.npmjs.org/scmp/-/scmp-1.0.0.tgz" }, "uid-safe": { "version": "1.1.0", - "from": "https://registry.npmjs.org/uid-safe/-/uid-safe-1.1.0.tgz", + "from": "uid-safe@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-1.1.0.tgz", "dependencies": { "native-or-bluebird": { "version": "1.1.2", - "from": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.1.2.tgz", + "from": "native-or-bluebird@>=1.1.2 <1.2.0", "resolved": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.1.2.tgz" } } @@ -8622,17 +8822,17 @@ }, "http-errors": { "version": "1.2.8", - "from": "https://registry.npmjs.org/http-errors/-/http-errors-1.2.8.tgz", + "from": "http-errors@>=1.2.8 <1.3.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.2.8.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "statuses": { "version": "1.2.1", - "from": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", + "from": "statuses@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz" } } @@ -8641,165 +8841,165 @@ }, "debug": { "version": "2.0.0", - "from": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", + "from": "debug@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "from": "ms@0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } }, "depd": { "version": "0.4.5", - "from": "https://registry.npmjs.org/depd/-/depd-0.4.5.tgz", + "from": "depd@0.4.5", "resolved": "https://registry.npmjs.org/depd/-/depd-0.4.5.tgz" }, "errorhandler": { "version": "1.2.4", - "from": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.2.4.tgz", + "from": "errorhandler@>=1.2.2 <1.3.0", "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.2.4.tgz", "dependencies": { "accepts": { "version": "1.1.4", - "from": "https://registry.npmjs.org/accepts/-/accepts-1.1.4.tgz", + "from": "accepts@>=1.1.3 <1.2.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.1.4.tgz", "dependencies": { "mime-types": { - "version": "2.0.9", - "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", + "version": "2.0.10", + "from": "mime-types@>=2.0.4 <2.1.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.10.tgz", "dependencies": { "mime-db": { - "version": "1.7.0", - "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz" + "version": "1.8.0", + "from": "mime-db@>=1.8.0 <1.9.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.8.0.tgz" } } }, "negotiator": { "version": "0.4.9", - "from": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz", + "from": "negotiator@0.4.9", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz" } } }, "escape-html": { "version": "1.0.1", - "from": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz", + "from": "escape-html@1.0.1", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz" } } }, "express-session": { "version": "1.8.2", - "from": "https://registry.npmjs.org/express-session/-/express-session-1.8.2.tgz", + "from": "express-session@>=1.8.2 <1.9.0", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.8.2.tgz", "dependencies": { "crc": { "version": "3.0.0", - "from": "https://registry.npmjs.org/crc/-/crc-3.0.0.tgz", + "from": "crc@3.0.0", "resolved": "https://registry.npmjs.org/crc/-/crc-3.0.0.tgz" }, "uid-safe": { "version": "1.0.1", - "from": "https://registry.npmjs.org/uid-safe/-/uid-safe-1.0.1.tgz", + "from": "uid-safe@1.0.1", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-1.0.1.tgz", "dependencies": { "mz": { "version": "1.3.0", - "from": "https://registry.npmjs.org/mz/-/mz-1.3.0.tgz", + "from": "mz@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/mz/-/mz-1.3.0.tgz", "dependencies": { "native-or-bluebird": { "version": "1.2.0", - "from": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.2.0.tgz", + "from": "native-or-bluebird@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.2.0.tgz" }, "thenify": { "version": "3.1.0", - "from": "https://registry.npmjs.org/thenify/-/thenify-3.1.0.tgz", + "from": "thenify@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.1.0.tgz" }, "thenify-all": { "version": "1.6.0", - "from": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "from": "thenify-all@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz" } } }, "base64-url": { "version": "1.2.1", - "from": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", + "from": "base64-url@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz" } } }, "utils-merge": { "version": "1.0.0", - "from": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "from": "utils-merge@1.0.0", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" } } }, "finalhandler": { "version": "0.2.0", - "from": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.2.0.tgz", + "from": "finalhandler@0.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.2.0.tgz", "dependencies": { "escape-html": { "version": "1.0.1", - "from": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz", + "from": "escape-html@1.0.1", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz" } } }, "fresh": { "version": "0.2.4", - "from": "https://registry.npmjs.org/fresh/-/fresh-0.2.4.tgz", + "from": "fresh@0.2.4", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.4.tgz" }, "media-typer": { "version": "0.3.0", - "from": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "from": "media-typer@0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" }, "method-override": { "version": "2.2.0", - "from": "https://registry.npmjs.org/method-override/-/method-override-2.2.0.tgz", + "from": "method-override@>=2.2.0 <2.3.0", "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.2.0.tgz", "dependencies": { "methods": { "version": "1.1.0", - "from": "https://registry.npmjs.org/methods/-/methods-1.1.0.tgz", + "from": "methods@1.1.0", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.0.tgz" }, "vary": { "version": "1.0.0", - "from": "https://registry.npmjs.org/vary/-/vary-1.0.0.tgz", + "from": "vary@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.0.tgz" } } }, "morgan": { "version": "1.3.2", - "from": "https://registry.npmjs.org/morgan/-/morgan-1.3.2.tgz", + "from": "morgan@>=1.3.2 <1.4.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.3.2.tgz", "dependencies": { "basic-auth": { "version": "1.0.0", - "from": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.0.tgz", + "from": "basic-auth@1.0.0", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.0.tgz" }, "on-finished": { "version": "2.1.0", - "from": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", + "from": "on-finished@2.1.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", "dependencies": { "ee-first": { "version": "1.0.5", - "from": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz", + "from": "ee-first@1.0.5", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz" } } @@ -8808,200 +9008,200 @@ }, "multiparty": { "version": "3.3.2", - "from": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", + "from": "multiparty@3.3.2", "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", "dependencies": { "readable-stream": { "version": "1.1.13", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "from": "readable-stream@>=1.1.9 <1.2.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "stream-counter": { "version": "0.2.0", - "from": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", + "from": "stream-counter@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz" } } }, "on-headers": { "version": "1.0.0", - "from": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.0.tgz", + "from": "on-headers@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.0.tgz" }, "parseurl": { "version": "1.3.0", - "from": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz", + "from": "parseurl@>=1.3.0 <1.4.0", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz" }, "qs": { "version": "2.2.4", - "from": "https://registry.npmjs.org/qs/-/qs-2.2.4.tgz", + "from": "qs@2.2.4", "resolved": "https://registry.npmjs.org/qs/-/qs-2.2.4.tgz" }, "response-time": { "version": "2.0.1", - "from": "https://registry.npmjs.org/response-time/-/response-time-2.0.1.tgz", + "from": "response-time@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.0.1.tgz" }, "serve-favicon": { "version": "2.1.7", - "from": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.1.7.tgz", + "from": "serve-favicon@>=2.1.5 <2.2.0", "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.1.7.tgz", "dependencies": { "etag": { "version": "1.5.1", - "from": "https://registry.npmjs.org/etag/-/etag-1.5.1.tgz", + "from": "etag@>=1.5.0 <1.6.0", "resolved": "https://registry.npmjs.org/etag/-/etag-1.5.1.tgz", "dependencies": { "crc": { "version": "3.2.1", - "from": "https://registry.npmjs.org/crc/-/crc-3.2.1.tgz", + "from": "crc@3.2.1", "resolved": "https://registry.npmjs.org/crc/-/crc-3.2.1.tgz" } } }, "ms": { "version": "0.6.2", - "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "from": "ms@0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } }, "serve-index": { "version": "1.2.1", - "from": "https://registry.npmjs.org/serve-index/-/serve-index-1.2.1.tgz", + "from": "serve-index@>=1.2.1 <1.3.0", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.2.1.tgz", "dependencies": { "accepts": { "version": "1.1.4", - "from": "https://registry.npmjs.org/accepts/-/accepts-1.1.4.tgz", + "from": "accepts@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.1.4.tgz", "dependencies": { "mime-types": { - "version": "2.0.9", - "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", + "version": "2.0.10", + "from": "mime-types@>=2.0.4 <2.1.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.10.tgz", "dependencies": { "mime-db": { - "version": "1.7.0", - "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz" + "version": "1.8.0", + "from": "mime-db@>=1.8.0 <1.9.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.8.0.tgz" } } }, "negotiator": { "version": "0.4.9", - "from": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz", + "from": "negotiator@0.4.9", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz" } } }, "batch": { "version": "0.5.1", - "from": "https://registry.npmjs.org/batch/-/batch-0.5.1.tgz", + "from": "batch@0.5.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.5.1.tgz" } } }, "serve-static": { "version": "1.6.5", - "from": "https://registry.npmjs.org/serve-static/-/serve-static-1.6.5.tgz", + "from": "serve-static@>=1.6.4 <1.7.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.6.5.tgz", "dependencies": { "escape-html": { "version": "1.0.1", - "from": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz", + "from": "escape-html@1.0.1", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz" }, "send": { "version": "0.9.3", - "from": "https://registry.npmjs.org/send/-/send-0.9.3.tgz", + "from": "send@0.9.3", "resolved": "https://registry.npmjs.org/send/-/send-0.9.3.tgz", "dependencies": { "destroy": { "version": "1.0.3", - "from": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz", + "from": "destroy@1.0.3", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz" }, "etag": { "version": "1.4.0", - "from": "https://registry.npmjs.org/etag/-/etag-1.4.0.tgz", + "from": "etag@>=1.4.0 <1.5.0", "resolved": "https://registry.npmjs.org/etag/-/etag-1.4.0.tgz", "dependencies": { "crc": { "version": "3.0.0", - "from": "https://registry.npmjs.org/crc/-/crc-3.0.0.tgz", + "from": "crc@3.0.0", "resolved": "https://registry.npmjs.org/crc/-/crc-3.0.0.tgz" } } }, "ms": { "version": "0.6.2", - "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "from": "ms@0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" }, "on-finished": { "version": "2.1.0", - "from": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", + "from": "on-finished@2.1.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", "dependencies": { "ee-first": { "version": "1.0.5", - "from": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz", + "from": "ee-first@1.0.5", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz" } } }, "range-parser": { "version": "1.0.2", - "from": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz", + "from": "range-parser@>=1.0.2 <1.1.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz" } } }, "utils-merge": { "version": "1.0.0", - "from": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "from": "utils-merge@1.0.0", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" } } }, "type-is": { "version": "1.5.7", - "from": "https://registry.npmjs.org/type-is/-/type-is-1.5.7.tgz", + "from": "type-is@>=1.5.2 <1.6.0", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.5.7.tgz", "dependencies": { "mime-types": { - "version": "2.0.9", - "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz", + "version": "2.0.10", + "from": "mime-types@>=2.0.9 <2.1.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.10.tgz", "dependencies": { "mime-db": { - "version": "1.7.0", - "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz" + "version": "1.8.0", + "from": "mime-db@>=1.8.0 <1.9.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.8.0.tgz" } } } @@ -9009,97 +9209,97 @@ }, "vhost": { "version": "3.0.0", - "from": "https://registry.npmjs.org/vhost/-/vhost-3.0.0.tgz", + "from": "vhost@>=3.0.0 <3.1.0", "resolved": "https://registry.npmjs.org/vhost/-/vhost-3.0.0.tgz" }, "pause": { "version": "0.0.1", - "from": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "from": "pause@0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz" } } }, "source-map": { "version": "0.1.43", - "from": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "from": "source-map@>=0.1.31 <0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", + "from": "amdefine@>=0.0.4", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } }, "memoizee": { "version": "0.3.8", - "from": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.8.tgz", + "from": "memoizee@>=0.3.8 <0.4.0", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.8.tgz", "dependencies": { "d": { "version": "0.1.1", - "from": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "from": "d@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz" }, "es5-ext": { "version": "0.10.6", - "from": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.6.tgz", + "from": "es5-ext@>=0.10.4 <0.11.0", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.6.tgz", "dependencies": { "es6-iterator": { "version": "0.1.3", - "from": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", + "from": "es6-iterator@>=0.1.3 <0.2.0", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz" }, "es6-symbol": { "version": "2.0.1", - "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", + "from": "es6-symbol@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz" } } }, "es6-weak-map": { "version": "0.1.2", - "from": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.2.tgz", + "from": "es6-weak-map@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.2.tgz", "dependencies": { "es6-iterator": { "version": "0.1.3", - "from": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", + "from": "es6-iterator@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", "dependencies": { "es6-symbol": { "version": "2.0.1", - "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", + "from": "es6-symbol@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz" } } }, "es6-symbol": { "version": "0.1.1", - "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-0.1.1.tgz", + "from": "es6-symbol@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-0.1.1.tgz" } } }, "event-emitter": { "version": "0.3.3", - "from": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.3.tgz", + "from": "event-emitter@>=0.3.1 <0.4.0", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.3.tgz" }, "lru-queue": { "version": "0.1.0", - "from": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "from": "lru-queue@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz" }, "next-tick": { "version": "0.2.2", - "from": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", + "from": "next-tick@>=0.2.2 <0.3.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz" }, "timers-ext": { "version": "0.1.0", - "from": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.0.tgz", + "from": "timers-ext@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.0.tgz" } } @@ -9108,113 +9308,113 @@ }, "karma-browserstack-launcher": { "version": "0.1.2", - "from": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-0.1.2.tgz", + "from": "karma-browserstack-launcher@0.1.2", "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-0.1.2.tgz", "dependencies": { "browserstack": { "version": "1.0.1", - "from": "https://registry.npmjs.org/browserstack/-/browserstack-1.0.1.tgz", + "from": "browserstack@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.0.1.tgz" }, "q": { "version": "0.9.7", - "from": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "from": "q@>=0.9.6 <0.10.0", "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz" } } }, "karma-chrome-launcher": { "version": "0.1.5", - "from": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-0.1.5.tgz", + "from": "karma-chrome-launcher@0.1.5", "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-0.1.5.tgz" }, "karma-firefox-launcher": { "version": "0.1.3", - "from": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-0.1.3.tgz", + "from": "karma-firefox-launcher@0.1.3", "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-0.1.3.tgz" }, "karma-jasmine": { "version": "0.1.5", - "from": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-0.1.5.tgz", + "from": "karma-jasmine@0.1.5", "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-0.1.5.tgz" }, "karma-junit-reporter": { "version": "0.2.2", - "from": "https://registry.npmjs.org/karma-junit-reporter/-/karma-junit-reporter-0.2.2.tgz", + "from": "karma-junit-reporter@0.2.2", "resolved": "https://registry.npmjs.org/karma-junit-reporter/-/karma-junit-reporter-0.2.2.tgz", "dependencies": { "xmlbuilder": { "version": "0.4.2", - "from": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-0.4.2.tgz", + "from": "xmlbuilder@0.4.2", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-0.4.2.tgz" } } }, "karma-ng-scenario": { "version": "0.1.0", - "from": "https://registry.npmjs.org/karma-ng-scenario/-/karma-ng-scenario-0.1.0.tgz", + "from": "karma-ng-scenario@0.1.0", "resolved": "https://registry.npmjs.org/karma-ng-scenario/-/karma-ng-scenario-0.1.0.tgz" }, "karma-sauce-launcher": { "version": "0.2.10", - "from": "https://registry.npmjs.org/karma-sauce-launcher/-/karma-sauce-launcher-0.2.10.tgz", + "from": "karma-sauce-launcher@0.2.10", "resolved": "https://registry.npmjs.org/karma-sauce-launcher/-/karma-sauce-launcher-0.2.10.tgz", "dependencies": { "wd": { "version": "0.3.11", - "from": "https://registry.npmjs.org/wd/-/wd-0.3.11.tgz", + "from": "wd@>=0.3.4 <0.4.0", "resolved": "https://registry.npmjs.org/wd/-/wd-0.3.11.tgz", "dependencies": { "archiver": { "version": "0.12.0", - "from": "https://registry.npmjs.org/archiver/-/archiver-0.12.0.tgz", + "from": "archiver@>=0.12.0 <0.13.0", "resolved": "https://registry.npmjs.org/archiver/-/archiver-0.12.0.tgz", "dependencies": { "buffer-crc32": { "version": "0.2.5", - "from": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.5.tgz", + "from": "buffer-crc32@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.5.tgz" }, "glob": { "version": "4.0.6", - "from": "https://registry.npmjs.org/glob/-/glob-4.0.6.tgz", + "from": "glob@>=4.0.6 <4.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-4.0.6.tgz", "dependencies": { "graceful-fs": { - "version": "3.0.5", - "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz" + "version": "3.0.6", + "from": "graceful-fs@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.6.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "1.0.0", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", + "from": "minimatch@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "once": { "version": "1.3.1", - "from": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "from": "once@>=1.3.0 <2.0.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -9223,59 +9423,59 @@ }, "lazystream": { "version": "0.1.0", - "from": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", + "from": "lazystream@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz" }, "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.26 <1.1.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "tar-stream": { "version": "1.0.2", - "from": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.0.2.tgz", + "from": "tar-stream@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.0.2.tgz", "dependencies": { "bl": { "version": "0.9.4", - "from": "https://registry.npmjs.org/bl/-/bl-0.9.4.tgz", + "from": "bl@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.4.tgz" }, "end-of-stream": { "version": "1.1.0", - "from": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.1.0.tgz", + "from": "end-of-stream@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.1.0.tgz", "dependencies": { "once": { "version": "1.3.1", - "from": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "from": "once@>=1.3.0 <1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -9284,25 +9484,25 @@ }, "xtend": { "version": "4.0.0", - "from": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz", + "from": "xtend@>=4.0.0 <5.0.0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" } } }, "zip-stream": { "version": "0.4.1", - "from": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.4.1.tgz", + "from": "zip-stream@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.4.1.tgz", "dependencies": { "compress-commons": { "version": "0.1.6", - "from": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.1.6.tgz", + "from": "compress-commons@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.1.6.tgz", "dependencies": { "crc32-stream": { - "version": "0.3.2", - "from": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.2.tgz", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.2.tgz" + "version": "0.3.3", + "from": "crc32-stream@>=0.3.1 <0.4.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.3.tgz" } } } @@ -9312,47 +9512,47 @@ }, "async": { "version": "0.9.0", - "from": "https://registry.npmjs.org/async/-/async-0.9.0.tgz", + "from": "async@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" }, "q": { "version": "1.0.1", - "from": "https://registry.npmjs.org/q/-/q-1.0.1.tgz", + "from": "q@>=1.0.1 <1.1.0", "resolved": "https://registry.npmjs.org/q/-/q-1.0.1.tgz" }, "request": { "version": "2.46.0", - "from": "https://registry.npmjs.org/request/-/request-2.46.0.tgz", + "from": "request@>=2.46.0 <2.47.0", "resolved": "https://registry.npmjs.org/request/-/request-2.46.0.tgz", "dependencies": { "bl": { "version": "0.9.4", - "from": "https://registry.npmjs.org/bl/-/bl-0.9.4.tgz", + "from": "bl@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.4.tgz", "dependencies": { "readable-stream": { "version": "1.0.33", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "from": "readable-stream@>=1.0.26 <1.1.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } @@ -9361,225 +9561,225 @@ }, "caseless": { "version": "0.6.0", - "from": "https://registry.npmjs.org/caseless/-/caseless-0.6.0.tgz", + "from": "caseless@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.6.0.tgz" }, "forever-agent": { "version": "0.5.2", - "from": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "from": "forever-agent@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" }, "form-data": { "version": "0.1.4", - "from": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "from": "form-data@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", "dependencies": { "combined-stream": { "version": "0.0.7", - "from": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "from": "combined-stream@>=0.0.4 <0.1.0", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", "dependencies": { "delayed-stream": { "version": "0.0.5", - "from": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "from": "delayed-stream@0.0.5", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" } } }, "mime": { "version": "1.2.11", - "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "from": "mime@>=1.2.11 <1.3.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" } } }, "json-stringify-safe": { "version": "5.0.0", - "from": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz", + "from": "json-stringify-safe@>=5.0.0 <5.1.0", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" }, "mime-types": { "version": "1.0.2", - "from": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "from": "mime-types@>=1.0.1 <1.1.0", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz" }, "node-uuid": { - "version": "1.4.2", - "from": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz" + "version": "1.4.3", + "from": "node-uuid@>=1.4.0 <1.5.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" }, "qs": { "version": "1.2.2", - "from": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz", + "from": "qs@>=1.2.0 <1.3.0", "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz" }, "tunnel-agent": { "version": "0.4.0", - "from": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz", + "from": "tunnel-agent@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz" }, "tough-cookie": { "version": "0.12.1", - "from": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", + "from": "tough-cookie@>=0.12.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", "dependencies": { "punycode": { "version": "1.3.2", - "from": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "from": "punycode@>=0.2.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" } } }, "http-signature": { "version": "0.10.1", - "from": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "from": "http-signature@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", "dependencies": { "assert-plus": { "version": "0.1.5", - "from": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "from": "assert-plus@>=0.1.5 <0.2.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" }, "asn1": { "version": "0.1.11", - "from": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "from": "asn1@0.1.11", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" }, "ctype": { "version": "0.5.3", - "from": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "from": "ctype@0.5.3", "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" } } }, "oauth-sign": { "version": "0.4.0", - "from": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.4.0.tgz", + "from": "oauth-sign@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.4.0.tgz" }, "hawk": { "version": "1.1.1", - "from": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "from": "hawk@1.1.1", "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", "dependencies": { "hoek": { "version": "0.9.1", - "from": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "from": "hoek@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" }, "boom": { "version": "0.4.2", - "from": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "from": "boom@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" }, "cryptiles": { "version": "0.2.2", - "from": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "from": "cryptiles@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" }, "sntp": { "version": "0.2.4", - "from": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "from": "sntp@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" } } }, "aws-sign2": { "version": "0.5.0", - "from": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "from": "aws-sign2@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" }, "stringstream": { "version": "0.0.4", - "from": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz", + "from": "stringstream@>=0.0.4 <0.1.0", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz" } } }, "underscore.string": { "version": "2.3.3", - "from": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "from": "underscore.string@>=2.3.3 <2.4.0", "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz" }, "vargs": { "version": "0.1.0", - "from": "https://registry.npmjs.org/vargs/-/vargs-0.1.0.tgz", + "from": "vargs@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/vargs/-/vargs-0.1.0.tgz" } } }, "sauce-connect-launcher": { "version": "0.6.1", - "from": "https://registry.npmjs.org/sauce-connect-launcher/-/sauce-connect-launcher-0.6.1.tgz", + "from": "sauce-connect-launcher@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/sauce-connect-launcher/-/sauce-connect-launcher-0.6.1.tgz", "dependencies": { "async": { "version": "0.9.0", - "from": "https://registry.npmjs.org/async/-/async-0.9.0.tgz", + "from": "async@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" }, "adm-zip": { "version": "0.4.7", - "from": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.7.tgz", + "from": "adm-zip@>=0.4.3 <0.5.0", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.7.tgz" }, "rimraf": { "version": "2.2.8", - "from": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "from": "rimraf@>=2.2.6 <2.3.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" } } }, "q": { "version": "0.9.7", - "from": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "from": "q@>=0.9.6 <0.10.0", "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz" }, "saucelabs": { "version": "0.1.1", - "from": "https://registry.npmjs.org/saucelabs/-/saucelabs-0.1.1.tgz", + "from": "saucelabs@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-0.1.1.tgz" } } }, "karma-script-launcher": { "version": "0.1.0", - "from": "https://registry.npmjs.org/karma-script-launcher/-/karma-script-launcher-0.1.0.tgz", + "from": "karma-script-launcher@0.1.0", "resolved": "https://registry.npmjs.org/karma-script-launcher/-/karma-script-launcher-0.1.0.tgz" }, "load-grunt-tasks": { "version": "0.6.0", - "from": "https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-0.6.0.tgz", + "from": "load-grunt-tasks@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-0.6.0.tgz", "dependencies": { "findup-sync": { "version": "0.1.3", - "from": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "from": "findup-sync@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", "dependencies": { "glob": { "version": "3.2.11", - "from": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "from": "glob@>=3.2.9 <3.3.0", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "from": "minimatch@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -9590,39 +9790,39 @@ }, "multimatch": { "version": "0.3.0", - "from": "https://registry.npmjs.org/multimatch/-/multimatch-0.3.0.tgz", + "from": "multimatch@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-0.3.0.tgz", "dependencies": { "array-differ": { "version": "0.1.0", - "from": "https://registry.npmjs.org/array-differ/-/array-differ-0.1.0.tgz", + "from": "array-differ@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-0.1.0.tgz" }, "array-union": { "version": "0.1.0", - "from": "https://registry.npmjs.org/array-union/-/array-union-0.1.0.tgz", + "from": "array-union@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-0.1.0.tgz", "dependencies": { "array-uniq": { "version": "0.1.1", - "from": "https://registry.npmjs.org/array-uniq/-/array-uniq-0.1.1.tgz", + "from": "array-uniq@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-0.1.1.tgz" } } }, "minimatch": { "version": "0.3.0", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "from": "minimatch@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -9633,120 +9833,120 @@ }, "lodash": { "version": "2.4.1", - "from": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz", + "from": "lodash@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" }, "marked": { "version": "0.3.3", - "from": "https://registry.npmjs.org/marked/-/marked-0.3.3.tgz", + "from": "marked@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.3.tgz" }, "node-html-encoder": { "version": "0.0.2", - "from": "https://registry.npmjs.org/node-html-encoder/-/node-html-encoder-0.0.2.tgz", + "from": "node-html-encoder@0.0.2", "resolved": "https://registry.npmjs.org/node-html-encoder/-/node-html-encoder-0.0.2.tgz" }, "promises-aplus-tests": { "version": "2.1.0", - "from": "https://registry.npmjs.org/promises-aplus-tests/-/promises-aplus-tests-2.1.0.tgz", + "from": "promises-aplus-tests@>=2.1.0 <2.2.0", "resolved": "https://registry.npmjs.org/promises-aplus-tests/-/promises-aplus-tests-2.1.0.tgz", "dependencies": { "mocha": { "version": "1.21.5", - "from": "https://registry.npmjs.org/mocha/-/mocha-1.21.5.tgz", + "from": "mocha@>=1.21.4 <1.22.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-1.21.5.tgz", "dependencies": { "commander": { "version": "2.3.0", - "from": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", + "from": "commander@2.3.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz" }, "debug": { "version": "2.0.0", - "from": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", + "from": "debug@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "from": "ms@0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } }, "diff": { "version": "1.0.8", - "from": "https://registry.npmjs.org/diff/-/diff-1.0.8.tgz", + "from": "diff@1.0.8", "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.8.tgz" }, "escape-string-regexp": { "version": "1.0.2", - "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "from": "escape-string-regexp@1.0.2", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz" }, "glob": { "version": "3.2.3", - "from": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", + "from": "glob@3.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", "dependencies": { "minimatch": { "version": "0.2.14", - "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "from": "minimatch@>=0.2.11 <0.3.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "graceful-fs": { "version": "2.0.3", - "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "from": "graceful-fs@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz" }, "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "growl": { "version": "1.8.1", - "from": "https://registry.npmjs.org/growl/-/growl-1.8.1.tgz", + "from": "growl@1.8.1", "resolved": "https://registry.npmjs.org/growl/-/growl-1.8.1.tgz" }, "jade": { "version": "0.26.3", - "from": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "from": "jade@0.26.3", "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", "dependencies": { "commander": { "version": "0.6.1", - "from": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "from": "commander@0.6.1", "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz" }, "mkdirp": { "version": "0.3.0", - "from": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "from": "mkdirp@0.3.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz" } } }, "mkdirp": { "version": "0.5.0", - "from": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "from": "mkdirp@0.5.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "from": "minimist@0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } @@ -9754,80 +9954,81 @@ } }, "sinon": { - "version": "1.12.2", - "from": "https://registry.npmjs.org/sinon/-/sinon-1.12.2.tgz", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.12.2.tgz", + "version": "1.14.1", + "from": "sinon@>=1.10.3 <2.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.14.1.tgz", "dependencies": { "formatio": { "version": "1.1.1", - "from": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", + "from": "formatio@1.1.1", "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", "dependencies": { "samsam": { "version": "1.1.2", - "from": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", + "from": "samsam@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz" } } }, "util": { "version": "0.10.3", - "from": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "from": "util@>=0.10.3 <1.0.0", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "from": "inherits@2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "lolex": { "version": "1.1.0", - "from": "https://registry.npmjs.org/lolex/-/lolex-1.1.0.tgz", + "from": "lolex@1.1.0", "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.1.0.tgz" } } }, "underscore": { "version": "1.6.0", - "from": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "from": "underscore@>=1.6.0 <1.7.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz" } } }, "protractor": { "version": "2.0.0", - "from": "protractor@2.0.0", + "from": "protractor@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/protractor/-/protractor-2.0.0.tgz", "dependencies": { "request": { "version": "2.36.0", - "from": "request@~2.36.0", + "from": "request@>=2.36.0 <2.37.0", "resolved": "https://registry.npmjs.org/request/-/request-2.36.0.tgz", "dependencies": { "qs": { "version": "0.6.6", - "from": "qs@~0.6.0", + "from": "qs@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz" }, "json-stringify-safe": { "version": "5.0.0", - "from": "json-stringify-safe@~5.0.0", + "from": "json-stringify-safe@>=5.0.0 <5.1.0", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" }, "mime": { "version": "1.2.11", - "from": "mime@~1.2.9", + "from": "mime@>=1.2.9 <1.3.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "forever-agent": { "version": "0.5.2", - "from": "forever-agent@~0.5.0", + "from": "forever-agent@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" }, "node-uuid": { "version": "1.4.3", - "from": "node-uuid@~1.4.0", + "from": "node-uuid@>=1.4.0 <1.5.0", "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" }, "tough-cookie": { @@ -9844,12 +10045,12 @@ }, "form-data": { "version": "0.1.4", - "from": "form-data@~0.1.0", + "from": "form-data@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", "dependencies": { "combined-stream": { "version": "0.0.7", - "from": "combined-stream@~0.0.4", + "from": "combined-stream@>=0.0.4 <0.1.0", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", "dependencies": { "delayed-stream": { @@ -9861,24 +10062,24 @@ }, "async": { "version": "0.9.0", - "from": "async@~0.9.0", + "from": "async@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" } } }, "tunnel-agent": { "version": "0.4.0", - "from": "tunnel-agent@~0.4.0", + "from": "tunnel-agent@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz" }, "http-signature": { "version": "0.10.1", - "from": "http-signature@~0.10.0", + "from": "http-signature@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", "dependencies": { "assert-plus": { "version": "0.1.5", - "from": "assert-plus@^0.1.5", + "from": "assert-plus@>=0.1.5 <0.2.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" }, "asn1": { @@ -9895,39 +10096,39 @@ }, "oauth-sign": { "version": "0.3.0", - "from": "oauth-sign@~0.3.0", + "from": "oauth-sign@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz" }, "hawk": { "version": "1.0.0", - "from": "hawk@~1.0.0", + "from": "hawk@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz", "dependencies": { "hoek": { "version": "0.9.1", - "from": "hoek@0.9.x", + "from": "hoek@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" }, "boom": { "version": "0.4.2", - "from": "boom@0.4.x", + "from": "boom@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" }, "cryptiles": { "version": "0.2.2", - "from": "cryptiles@0.2.x", + "from": "cryptiles@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" }, "sntp": { "version": "0.2.4", - "from": "sntp@0.2.x", + "from": "sntp@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" } } }, "aws-sign2": { "version": "0.5.0", - "from": "aws-sign2@~0.5.0", + "from": "aws-sign2@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" } } @@ -9939,44 +10140,44 @@ "dependencies": { "rimraf": { "version": "2.3.2", - "from": "rimraf@^2.2.8", + "from": "rimraf@>=2.2.8 <3.0.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.3.2.tgz", "dependencies": { "glob": { "version": "4.5.3", - "from": "glob@^4.4.2", + "from": "glob@>=4.4.2 <5.0.0", "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", "dependencies": { "inflight": { "version": "1.0.4", - "from": "inflight@^1.0.4", + "from": "inflight@>=1.0.4 <2.0.0", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "wrappy@1", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } }, "inherits": { "version": "2.0.1", - "from": "inherits@2", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "2.0.4", - "from": "minimatch@^2.0.1", + "from": "minimatch@>=2.0.1 <3.0.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.4.tgz", "dependencies": { "brace-expansion": { "version": "1.1.0", - "from": "brace-expansion@^1.0.0", + "from": "brace-expansion@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz", "dependencies": { "balanced-match": { "version": "0.2.0", - "from": "balanced-match@^0.2.0", + "from": "balanced-match@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz" }, "concat-map": { @@ -9990,12 +10191,12 @@ }, "once": { "version": "1.3.1", - "from": "once@^1.3.0", + "from": "once@>=1.3.0 <2.0.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "wrappy@1", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -10011,7 +10212,7 @@ }, "ws": { "version": "0.7.1", - "from": "ws@^0.7.1", + "from": "ws@>=0.7.1 <0.8.0", "resolved": "https://registry.npmjs.org/ws/-/ws-0.7.1.tgz", "dependencies": { "options": { @@ -10021,39 +10222,39 @@ }, "ultron": { "version": "1.0.1", - "from": "ultron@1.0.x", + "from": "ultron@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.1.tgz" }, "bufferutil": { "version": "1.0.1", - "from": "bufferutil@1.0.x", + "from": "bufferutil@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-1.0.1.tgz", "dependencies": { "bindings": { "version": "1.2.1", - "from": "bindings@1.2.x", + "from": "bindings@>=1.2.0 <1.3.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" }, "nan": { "version": "1.6.2", - "from": "nan@1.6.x", + "from": "nan@>=1.6.0 <1.7.0", "resolved": "https://registry.npmjs.org/nan/-/nan-1.6.2.tgz" } } }, "utf-8-validate": { "version": "1.0.1", - "from": "utf-8-validate@1.0.x", + "from": "utf-8-validate@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-1.0.1.tgz", "dependencies": { "bindings": { "version": "1.2.1", - "from": "bindings@1.2.x", + "from": "bindings@>=1.2.0 <1.3.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" }, "nan": { "version": "1.6.2", - "from": "nan@1.6.x", + "from": "nan@>=1.6.0 <1.7.0", "resolved": "https://registry.npmjs.org/nan/-/nan-1.6.2.tgz" } } @@ -10067,7 +10268,7 @@ "dependencies": { "sax": { "version": "0.6.1", - "from": "sax@0.6.x", + "from": "sax@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz" }, "xmlbuilder": { @@ -10077,7 +10278,7 @@ "dependencies": { "lodash": { "version": "3.5.0", - "from": "lodash@~3.5.0", + "from": "lodash@>=3.5.0 <3.6.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.5.0.tgz" } } @@ -10098,7 +10299,8 @@ }, "jasminewd2": { "version": "0.0.3", - "from": "jasminewd2@0.0.3" + "from": "jasminewd2@0.0.3", + "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-0.0.3.tgz" }, "jasmine": { "version": "2.1.1", @@ -10107,39 +10309,39 @@ "dependencies": { "jasmine-core": { "version": "2.1.3", - "from": "jasmine-core@~2.1.0", + "from": "jasmine-core@>=2.1.0 <2.2.0", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.1.3.tgz" } } }, "saucelabs": { "version": "0.1.1", - "from": "saucelabs@~0.1.0", + "from": "saucelabs@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-0.1.1.tgz" }, "glob": { "version": "3.2.11", - "from": "glob@~3.2", + "from": "glob@>=3.2.0 <3.3.0", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@2", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", - "from": "minimatch@0.3", + "from": "minimatch@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@2", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@~1.0.0", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -10153,17 +10355,17 @@ }, "optimist": { "version": "0.6.1", - "from": "optimist@~0.6.0", + "from": "optimist@*", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "dependencies": { "wordwrap": { "version": "0.0.2", - "from": "wordwrap@~0.0.2", + "from": "wordwrap@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" }, "minimist": { "version": "0.0.10", - "from": "minimist@~0.0.1", + "from": "minimist@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } @@ -10175,7 +10377,7 @@ }, "source-map-support": { "version": "0.2.10", - "from": "source-map-support@~0.2.6", + "from": "source-map-support@>=0.2.6 <0.3.0", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.10.tgz", "dependencies": { "source-map": { @@ -10194,54 +10396,54 @@ }, "html-entities": { "version": "1.1.2", - "from": "html-entities@~1.1.1", + "from": "html-entities@>=1.1.1 <1.2.0", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.1.2.tgz" }, "accessibility-developer-tools": { "version": "2.6.0", - "from": "accessibility-developer-tools@~2.6.0", + "from": "accessibility-developer-tools@>=2.6.0 <2.7.0", "resolved": "https://registry.npmjs.org/accessibility-developer-tools/-/accessibility-developer-tools-2.6.0.tgz" } } }, "q": { "version": "1.0.1", - "from": "https://registry.npmjs.org/q/-/q-1.0.1.tgz", + "from": "q@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/q/-/q-1.0.1.tgz" }, "q-io": { - "version": "1.11.6", - "from": "https://registry.npmjs.org/q-io/-/q-io-1.11.6.tgz", - "resolved": "https://registry.npmjs.org/q-io/-/q-io-1.11.6.tgz", + "version": "1.12.0", + "from": "q-io@>=1.10.9 <2.0.0", + "resolved": "https://registry.npmjs.org/q-io/-/q-io-1.12.0.tgz", "dependencies": { "qs": { "version": "1.2.2", - "from": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz", + "from": "qs@>=1.2.1 <2.0.0", "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz" }, "url2": { "version": "0.0.0", - "from": "https://registry.npmjs.org/url2/-/url2-0.0.0.tgz", + "from": "url2@>=0.0.0 <0.0.1", "resolved": "https://registry.npmjs.org/url2/-/url2-0.0.0.tgz" }, "mime": { "version": "1.3.4", - "from": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "from": "mime@>=1.2.11 <2.0.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" }, "mimeparse": { "version": "0.1.4", - "from": "https://registry.npmjs.org/mimeparse/-/mimeparse-0.1.4.tgz", + "from": "mimeparse@>=0.1.4 <0.2.0", "resolved": "https://registry.npmjs.org/mimeparse/-/mimeparse-0.1.4.tgz" }, "collections": { "version": "0.2.2", - "from": "https://registry.npmjs.org/collections/-/collections-0.2.2.tgz", + "from": "collections@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/collections/-/collections-0.2.2.tgz", "dependencies": { "weak-map": { "version": "1.0.0", - "from": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.0.tgz", + "from": "weak-map@1.0.0", "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.0.tgz" } } @@ -10250,39 +10452,39 @@ }, "qq": { "version": "0.3.5", - "from": "https://registry.npmjs.org/qq/-/qq-0.3.5.tgz", + "from": "qq@>=0.3.5 <0.4.0", "resolved": "https://registry.npmjs.org/qq/-/qq-0.3.5.tgz", "dependencies": { "q": { "version": "0.8.4", - "from": "https://registry.npmjs.org/q/-/q-0.8.4.tgz", + "from": "q@0.8.4", "resolved": "https://registry.npmjs.org/q/-/q-0.8.4.tgz" } } }, "rewire": { "version": "2.1.5", - "from": "https://registry.npmjs.org/rewire/-/rewire-2.1.5.tgz", + "from": "rewire@>=2.1.0 <2.2.0", "resolved": "https://registry.npmjs.org/rewire/-/rewire-2.1.5.tgz" }, "semver": { "version": "4.0.3", - "from": "https://registry.npmjs.org/semver/-/semver-4.0.3.tgz", + "from": "semver@>=4.0.3 <4.1.0", "resolved": "https://registry.npmjs.org/semver/-/semver-4.0.3.tgz" }, "shelljs": { "version": "0.3.0", - "from": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", + "from": "shelljs@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz" }, "sorted-object": { "version": "1.0.0", - "from": "https://registry.npmjs.org/sorted-object/-/sorted-object-1.0.0.tgz", + "from": "sorted-object@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/sorted-object/-/sorted-object-1.0.0.tgz" }, "stringmap": { "version": "0.2.2", - "from": "https://registry.npmjs.org/stringmap/-/stringmap-0.2.2.tgz", + "from": "stringmap@>=0.2.2 <0.3.0", "resolved": "https://registry.npmjs.org/stringmap/-/stringmap-0.2.2.tgz" } } From da5611005b3bc08092cc7787199686483a02bdf6 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Tue, 24 Mar 2015 21:00:28 +0100 Subject: [PATCH 183/489] fix(ngModel): allow setting model to NaN when asyncValidator is present Closes #11315 Closes #11411 --- src/ng/directive/ngModel.js | 5 ++++- test/ng/directive/ngModelSpec.js | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/ng/directive/ngModel.js b/src/ng/directive/ngModel.js index 6098cd08a829..a3446c7ff1a9 100644 --- a/src/ng/directive/ngModel.js +++ b/src/ng/directive/ngModel.js @@ -810,7 +810,10 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ // if scope model value and ngModel value are out of sync // TODO(perf): why not move this to the action fn? - if (modelValue !== ctrl.$modelValue) { + if (modelValue !== ctrl.$modelValue && + // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator + (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue) + ) { ctrl.$modelValue = ctrl.$$rawModelValue = modelValue; parserValid = undefined; diff --git a/test/ng/directive/ngModelSpec.js b/test/ng/directive/ngModelSpec.js index 019f078e6fad..438fef1325e4 100644 --- a/test/ng/directive/ngModelSpec.js +++ b/test/ng/directive/ngModelSpec.js @@ -578,6 +578,29 @@ describe('ngModel', function() { dealoc(form); })); + + + it('should set NaN as the $modelValue when an asyncValidator is present', + inject(function($q) { + + ctrl.$asyncValidators.test = function() { + return $q(function(resolve, reject) { + resolve(); + }); + }; + + scope.$apply('value = 10'); + expect(ctrl.$modelValue).toBe(10); + + expect(function() { + scope.$apply(function() { + scope.value = NaN; + }); + }).not.toThrow(); + + expect(ctrl.$modelValue).toBeNaN(); + + })); }); From 22e3dc369d1a88e69b5c17d31e34837e6cc27586 Mon Sep 17 00:00:00 2001 From: Shahar Talmi Date: Sat, 21 Mar 2015 21:46:00 +0200 Subject: [PATCH 184/489] fix(cookieReader): safely access $document so it can be mocked Closes #11373 Closes #11388 --- src/ng/cookieReader.js | 7 ++++--- test/ng/documentSpec.js | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/ng/cookieReader.js b/src/ng/cookieReader.js index 53bc279f4269..b22d96096893 100644 --- a/src/ng/cookieReader.js +++ b/src/ng/cookieReader.js @@ -10,7 +10,7 @@ * @return {Object} a key/value map of the current cookies */ function $$CookieReader($document) { - var rawDocument = $document[0]; + var rawDocument = $document[0] || {}; var lastCookies = {}; var lastCookieString = ''; @@ -24,9 +24,10 @@ function $$CookieReader($document) { return function() { var cookieArray, cookie, i, index, name; + var currentCookieString = rawDocument.cookie || ''; - if (rawDocument.cookie !== lastCookieString) { - lastCookieString = rawDocument.cookie; + if (currentCookieString !== lastCookieString) { + lastCookieString = currentCookieString; cookieArray = lastCookieString.split('; '); lastCookies = {}; diff --git a/test/ng/documentSpec.js b/test/ng/documentSpec.js index 064904a26db0..3fbca1d7a048 100644 --- a/test/ng/documentSpec.js +++ b/test/ng/documentSpec.js @@ -6,4 +6,24 @@ describe('$document', function() { it("should inject $document", inject(function($document) { expect($document).toEqual(jqLite(document)); })); + + + it('should be able to mock $document object', function() { + module({$document: {}}); + inject(function($httpBackend, $http) { + $httpBackend.expectGET('/dummy').respond('dummy'); + $http.get('/dummy'); + $httpBackend.flush(); + }); + }); + + + it('should be able to mock $document array', function() { + module({$document: [{}]}); + inject(function($httpBackend, $http) { + $httpBackend.expectGET('/dummy').respond('dummy'); + $http.get('/dummy'); + $httpBackend.flush(); + }); + }); }); From 4a89330d68d88a9c3b9ecc0925289946b90899bd Mon Sep 17 00:00:00 2001 From: tomoyuki kashiro Date: Sun, 22 Feb 2015 21:57:17 +0900 Subject: [PATCH 185/489] chore(version-info): modify versioning for < v1.0.2 Angular v1.0.1 and earlier did not have valid versions and had a different docs url format, so you can not access their api docs from the version drop-down. Closes #11132 --- docs/app/src/versions.js | 14 ++++++++------ lib/versions/version-info.js | 8 +++++++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/docs/app/src/versions.js b/docs/app/src/versions.js index 708e613d3471..4f299c265bf2 100644 --- a/docs/app/src/versions.js +++ b/docs/app/src/versions.js @@ -21,11 +21,13 @@ angular.module('versions', []) }; $scope.jumpToDocsVersion = function(version) { - var currentPagePath = $location.path().replace(/\/$/, ''); - - // TODO: We need to do some munging of the path for different versions of the API... - - - $window.location = version.docsUrl + currentPagePath; + var currentPagePath = $location.path().replace(/\/$/, ''), + url = ''; + if (version.isOldDocsUrl) { + url = version.docsUrl; + }else{ + url = version.docsUrl + currentPagePath; + } + $window.location = url; }; }]); diff --git a/lib/versions/version-info.js b/lib/versions/version-info.js index d4a4208addda..9de1d7de68a6 100644 --- a/lib/versions/version-info.js +++ b/lib/versions/version-info.js @@ -110,10 +110,16 @@ var getPreviousVersions = function() { }) .filter() .map(function(version) { + // angular.js didn't follow semantic version until 1.20rc1 + if ((version.major === 1 && version.minor === 0 && version.prerelease.length > 0) || (version.major === 1 && version.minor === 2 && version.prerelease[0] === 'rc1')) { + version.version = [version.major, version.minor, version.patch].join('.') + version.prerelease.join(''); + version.raw = 'v' + version.version; + } version.docsUrl = 'http://code.angularjs.org/' + version.version + '/docs'; // Versions before 1.0.2 had a different docs folder name - if (version.major < 1 || (version.major === 1 && version.minor === 0 && version.dot < 2)) { + if (version.major < 1 || (version.major === 1 && version.minor === 0 && version.patch < 2)) { version.docsUrl += '-' + version.version; + version.isOldDocsUrl = true; } return version; }) From 26fd0b413e66ce815b0c49e863a83282c79e7324 Mon Sep 17 00:00:00 2001 From: Pawel Kozlowski Date: Fri, 3 Apr 2015 12:27:27 +0200 Subject: [PATCH 186/489] docs($http): clarify side effects of transformRequest functions Closes #11438 Closes #11503 --- CHANGELOG.md | 28 ++++++++++++++++++++++++++++ test/ng/httpSpec.js | 17 +++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 898ef13e925d..18891fa8bed7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -249,6 +249,34 @@ end of the container containing the ngMessages directive).
``` +- **$http:** due to [5da1256](https://github.com/angular/angular.js/commit/5da1256fc2812d5b28fb0af0de81256054856369), + +`transformRequest` functions can no longer modify request headers. + +Before this commit `transformRequest` could modify request headers, ex.: + +```javascript +function requestTransform(data, headers) { + headers = angular.extend(headers(), { + 'X-MY_HEADER': 'abcd' + }); + } + return angular.toJson(data); +} +``` + +This behavior was unintended and undocumented, so the change should affect very few applications. If one +needs to dynamically add / remove headers it should be done in a header function, for example: + +```javascript +$http.get(url, { + headers: { + 'X-MY_HEADER': function(config) { + return 'abcd'; //you've got access to a request config object to specify header value dynamically + } + } +}) +``` # 1.3.14 instantaneous-browserification (2015-02-24) diff --git a/test/ng/httpSpec.js b/test/ng/httpSpec.js index a73f2ae75e5f..79078321c3b6 100644 --- a/test/ng/httpSpec.js +++ b/test/ng/httpSpec.js @@ -1128,6 +1128,23 @@ describe('$http', function() { expect(callback).toHaveBeenCalledOnce(); }); + it('should not allow modifications to headers in a transform functions', function() { + var config = { + headers: {'Accept': 'bar'}, + transformRequest: function(data, headers) { + angular.extend(headers(), { + 'Accept': 'foo' + }); + } + }; + + $httpBackend.expect('GET', '/url', undefined, {Accept: 'bar'}).respond(200); + $http.get('/url', config).success(callback); + $httpBackend.flush(); + + expect(callback).toHaveBeenCalledOnce(); + }); + it('should pipeline more functions', function() { function first(d, h) {return d + '-first' + ':' + h('h1');} function second(d) {return uppercase(d);} From ae5efeb5032eb69cd99531176ead8b43c2ec92e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Thu, 2 Apr 2015 20:52:30 -0700 Subject: [PATCH 187/489] feat($animate): complete refactor of internal animation code All of ngAnimate has been rewritten to make the internals of the animation code more flexible, reuseable and performant. BREAKING CHANGE: JavaSript and CSS animations can no longer be run in parallel. With earlier versions of ngAnimate, both CSS and JS animations would be run together when multiple animations were detected. This feature has now been removed, however, the same effect, with even more possibilities, can be achieved by injecting `$animateCss` into a JavaScript-defined animation and creating custom CSS-based animations from there. Read the ngAnimate docs for more info. BREAKING CHANGE: The function params for `$animate.enabled()` when an element is used are now flipped. This fix allows the function to act as a getter when a single element param is provided. ```js // < 1.4 $animate.enabled(false, element); // 1.4+ $animate.enabled(element, false); ``` BREAKING CHANGE: In addition to disabling the children of the element, `$animate.enabled(element, false)` will now also disable animations on the element itself. BREAKING CHANGE: Animation-related callbacks are now fired on `$animate.on` instead of directly being on the element. ```js // < 1.4 element.on('$animate:before', function(e, data) { if (data.event === 'enter') { ... } }); element.off('$animate:before', fn); // 1.4+ $animate.on(element, 'enter', function(data) { //... }); $animate.off(element, 'enter', fn); ``` BREAKING CHANGE: There is no need to call `$scope.$apply` or `$scope.$digest` inside of a animation promise callback anymore since the promise is resolved within a digest automatically (but a digest is not run unless the promise is chained). ```js // < 1.4 $animate.enter(element).then(function() { $scope.$apply(function() { $scope.explode = true; }); }); // 1.4+ $animate.enter(element).then(function() { $scope.explode = true; }); ``` BREAKING CHANGE: When an enter, leave or move animation is triggered then it will always end any pending or active parent class based animations (animations triggered via ngClass) in order to ensure that any CSS styles are resolved in time. --- angularFiles.js | 11 +- css/angular.css | 8 + docs/content/api/index.ngdoc | 2 +- docs/content/guide/animations.ngdoc | 4 +- src/AngularPublic.js | 4 + src/loader.js | 2 +- src/ng/animate.js | 570 +- src/ng/directive/ngClass.js | 4 +- src/ngAnimate/.jshintrc | 36 +- src/ngAnimate/animate.js | 2130 ------ src/ngAnimate/animateChildrenDirective.js | 15 + src/ngAnimate/animateCss.js | 997 +++ src/ngAnimate/animateCssDriver.js | 218 + src/ngAnimate/animateJs.js | 250 + src/ngAnimate/animateJsDriver.js | 61 + src/ngAnimate/animateQueue.js | 551 ++ src/ngAnimate/animateRunner.js | 151 + src/ngAnimate/animation.js | 288 + src/ngAnimate/module.js | 508 ++ src/ngAnimate/shared.js | 230 + src/ngMock/angular-mocks.js | 7 +- test/.jshintrc | 2 + test/helpers/privateMocks.js | 14 +- test/helpers/testabilityPatch.js | 11 + test/ng/animateSpec.js | 62 +- test/ng/directive/formSpec.js | 1 + test/ng/directive/ngClassSpec.js | 41 +- test/ng/directive/ngModelSpec.js | 8 +- test/ng/directive/ngRepeatSpec.js | 5 +- test/ngAnimate/.jshintrc | 13 + test/ngAnimate/animateCssDriverSpec.js | 894 +++ test/ngAnimate/animateCssSpec.js | 2428 +++++++ test/ngAnimate/animateJsDriverSpec.js | 178 + test/ngAnimate/animateJsSpec.js | 672 ++ test/ngAnimate/animateRunnerSpec.js | 340 + test/ngAnimate/animateSpec.js | 6179 +++-------------- .../ngAnimate/animationHelperFunctionsSpec.js | 135 + test/ngAnimate/animationSpec.js | 858 +++ test/ngRoute/directive/ngViewSpec.js | 4 +- 39 files changed, 10237 insertions(+), 7655 deletions(-) delete mode 100644 src/ngAnimate/animate.js create mode 100644 src/ngAnimate/animateChildrenDirective.js create mode 100644 src/ngAnimate/animateCss.js create mode 100644 src/ngAnimate/animateCssDriver.js create mode 100644 src/ngAnimate/animateJs.js create mode 100644 src/ngAnimate/animateJsDriver.js create mode 100644 src/ngAnimate/animateQueue.js create mode 100644 src/ngAnimate/animateRunner.js create mode 100644 src/ngAnimate/animation.js create mode 100644 src/ngAnimate/module.js create mode 100644 src/ngAnimate/shared.js create mode 100644 test/ngAnimate/.jshintrc create mode 100644 test/ngAnimate/animateCssDriverSpec.js create mode 100644 test/ngAnimate/animateCssSpec.js create mode 100644 test/ngAnimate/animateJsDriverSpec.js create mode 100644 test/ngAnimate/animateJsSpec.js create mode 100644 test/ngAnimate/animateRunnerSpec.js create mode 100644 test/ngAnimate/animationHelperFunctionsSpec.js create mode 100644 test/ngAnimate/animationSpec.js diff --git a/angularFiles.js b/angularFiles.js index bf6d2141a122..f2ffb66c639b 100755 --- a/angularFiles.js +++ b/angularFiles.js @@ -87,7 +87,16 @@ var angularFiles = { 'angularModules': { 'ngAnimate': [ - 'src/ngAnimate/animate.js' + 'src/ngAnimate/shared.js', + 'src/ngAnimate/animateChildrenDirective.js', + 'src/ngAnimate/animateCss.js', + 'src/ngAnimate/animateCssDriver.js', + 'src/ngAnimate/animateJs.js', + 'src/ngAnimate/animateJsDriver.js', + 'src/ngAnimate/animateQueue.js', + 'src/ngAnimate/animateRunner.js', + 'src/ngAnimate/animation.js', + 'src/ngAnimate/module.js' ], 'ngCookies': [ 'src/ngCookies/cookies.js', diff --git a/css/angular.css b/css/angular.css index 81da6c4a111c..c23a0b3d1876 100644 --- a/css/angular.css +++ b/css/angular.css @@ -9,3 +9,11 @@ ng\:form { display: block; } + +.ng-animate-shim { + visibility:hidden; +} + +.ng-animate-anchor { + position:absolute; +} diff --git a/docs/content/api/index.ngdoc b/docs/content/api/index.ngdoc index f74d35842852..d2a91e06830d 100644 --- a/docs/content/api/index.ngdoc +++ b/docs/content/api/index.ngdoc @@ -140,7 +140,7 @@ or JavaScript callbacks. {@link ngAnimate#service Services / Factories} - Use {@link ngAnimate.$animate $animate} to trigger animation operations within your directive code. + Use {@link ng.$animate $animate} to trigger animation operations within your directive code. diff --git a/docs/content/guide/animations.ngdoc b/docs/content/guide/animations.ngdoc index 2af9cf23fd6a..14b62f1f9d1b 100644 --- a/docs/content/guide/animations.ngdoc +++ b/docs/content/guide/animations.ngdoc @@ -253,7 +253,7 @@ The table below explains in detail which animation events are triggered | {@link ng.directive:ngClass#animations ngClass or {{class}}} | add and remove | | {@link ng.directive:ngShow#animations ngShow & ngHide} | add and remove (the ng-hide class value) | -For a full breakdown of the steps involved during each animation event, refer to the {@link ngAnimate.$animate API docs}. +For a full breakdown of the steps involved during each animation event, refer to the {@link ng.$animate API docs}. ## How do I use animations in my own directives? @@ -276,6 +276,6 @@ myModule.directive('my-directive', ['$animate', function($animate) { ## More about animations -For a full breakdown of each method available on `$animate`, see the {@link ngAnimate.$animate API documentation}. +For a full breakdown of each method available on `$animate`, see the {@link ng.$animate API documentation}. To see a complete demo, see the {@link tutorial/step_12 animation step within the AngularJS phonecat tutorial}. diff --git a/src/AngularPublic.js b/src/AngularPublic.js index 9a7b182f669b..3f530626d3e2 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -57,6 +57,8 @@ $AnchorScrollProvider, $AnimateProvider, + $$CoreAnimateQueueProvider, + $$CoreAnimateRunnerProvider, $BrowserProvider, $CacheFactoryProvider, $ControllerProvider, @@ -217,6 +219,8 @@ function publishExternalAPI(angular) { $provide.provider({ $anchorScroll: $AnchorScrollProvider, $animate: $AnimateProvider, + $$animateQueue: $$CoreAnimateQueueProvider, + $$AnimateRunner: $$CoreAnimateRunnerProvider, $browser: $BrowserProvider, $cacheFactory: $CacheFactoryProvider, $controller: $ControllerProvider, diff --git a/src/loader.js b/src/loader.js index 997a6c933d4b..02a2e2d66c43 100644 --- a/src/loader.js +++ b/src/loader.js @@ -218,7 +218,7 @@ function setupModuleLoader(window) { * * * Defines an animation hook that can be later used with - * {@link ngAnimate.$animate $animate} service and directives that use this service. + * {@link $animate $animate} service and directives that use this service. * * ```js * module.animation('.animation-name', function($inject1, $inject2) { diff --git a/src/ng/animate.js b/src/ng/animate.js index f268773ef2af..449bbc6c34e7 100644 --- a/src/ng/animate.js +++ b/src/ng/animate.js @@ -1,6 +1,151 @@ 'use strict'; var $animateMinErr = minErr('$animate'); +var ELEMENT_NODE = 1; + +function mergeClasses(a,b) { + if (!a && !b) return ''; + if (!a) return b; + if (!b) return a; + if (isArray(a)) a = a.join(' '); + if (isArray(b)) b = b.join(' '); + return a + ' ' + b; +} + +function extractElementNode(element) { + for (var i = 0; i < element.length; i++) { + var elm = element[i]; + if (elm.nodeType === ELEMENT_NODE) { + return elm; + } + } +} + +function splitClasses(classes) { + if (isString(classes)) { + classes = classes.split(' '); + } + + var obj = {}; + forEach(classes, function(klass) { + // sometimes the split leaves empty string values + // incase extra spaces were applied to the options + if (klass.length) { + obj[klass] = true; + } + }); + return obj; +} + +var $$CoreAnimateRunnerProvider = function() { + this.$get = ['$q', '$$rAF', function($q, $$rAF) { + function AnimateRunner() {} + AnimateRunner.all = noop; + AnimateRunner.chain = noop; + AnimateRunner.prototype = { + end: noop, + cancel: noop, + resume: noop, + pause: noop, + complete: noop, + then: function(pass, fail) { + return $q(function(resolve) { + $$rAF(function() { + resolve(); + }); + }).then(pass, fail); + } + }; + return AnimateRunner; + }]; +}; + +// this is prefixed with Core since it conflicts with +// the animateQueueProvider defined in ngAnimate/animateQueue.js +var $$CoreAnimateQueueProvider = function() { + var postDigestQueue = new HashMap(); + var postDigestElements = []; + + this.$get = ['$$AnimateRunner', '$rootScope', + function($$AnimateRunner, $rootScope) { + return { + enabled: noop, + on: noop, + off: noop, + + push: function(element, event, options, domOperation) { + domOperation && domOperation(); + + options = options || {}; + options.from && element.css(options.from); + options.to && element.css(options.to); + + if (options.addClass || options.removeClass) { + addRemoveClassesPostDigest(element, options.addClass, options.removeClass); + } + + return new $$AnimateRunner(); // jshint ignore:line + } + }; + + function addRemoveClassesPostDigest(element, add, remove) { + var data = postDigestQueue.get(element); + var classVal; + + if (!data) { + postDigestQueue.put(element, data = {}); + postDigestElements.push(element); + } + + if (add) { + forEach(add.split(' '), function(className) { + if (className) { + data[className] = true; + } + }); + } + + if (remove) { + forEach(remove.split(' '), function(className) { + if (className) { + data[className] = false; + } + }); + } + + if (postDigestElements.length > 1) return; + + $rootScope.$$postDigest(function() { + forEach(postDigestElements, function(element) { + var data = postDigestQueue.get(element); + if (data) { + var existing = splitClasses(element.attr('class')); + var toAdd = ''; + var toRemove = ''; + forEach(data, function(status, className) { + var hasClass = !!existing[className]; + if (status !== hasClass) { + if (status) { + toAdd += (toAdd.length ? ' ' : '') + className; + } else { + toRemove += (toRemove.length ? ' ' : '') + className; + } + } + }); + + forEach(element, function(elm) { + toAdd && jqLiteAddClass(elm, toAdd); + toRemove && jqLiteRemoveClass(elm, toRemove); + }); + postDigestQueue.remove(element); + } + }); + + postDigestElements.length = 0; + }); + } + }]; +}; /** * @ngdoc provider @@ -8,20 +153,18 @@ var $animateMinErr = minErr('$animate'); * * @description * Default implementation of $animate that doesn't perform any animations, instead just - * synchronously performs DOM - * updates and calls done() callbacks. + * synchronously performs DOM updates and resolves the returned runner promise. * - * In order to enable animations the ngAnimate module has to be loaded. + * In order to enable animations the `ngAnimate` module has to be loaded. * - * To see the functional implementation check out src/ngAnimate/animate.js + * To see the functional implementation check out `src/ngAnimate/animate.js`. */ var $AnimateProvider = ['$provide', function($provide) { + var provider = this; + this.$$registeredAnimations = []; - this.$$selectors = {}; - - - /** + /** * @ngdoc method * @name $animateProvider#register * @@ -30,33 +173,43 @@ var $AnimateProvider = ['$provide', function($provide) { * animation object which contains callback functions for each event that is expected to be * animated. * - * * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction` - * must be called once the element animation is complete. If a function is returned then the - * animation service will use this function to cancel the animation whenever a cancel event is - * triggered. + * * `eventFn`: `function(element, ... , doneFunction, options)` + * The element to animate, the `doneFunction` and the options fed into the animation. Depending + * on the type of animation additional arguments will be injected into the animation function. The + * list below explains the function signatures for the different animation methods: * + * - setClass: function(element, addedClasses, removedClasses, doneFunction, options) + * - addClass: function(element, addedClasses, doneFunction, options) + * - removeClass: function(element, removedClasses, doneFunction, options) + * - enter, leave, move: function(element, doneFunction, options) + * - animate: function(element, fromStyles, toStyles, doneFunction, options) + * + * Make sure to trigger the `doneFunction` once the animation is fully complete. * * ```js * return { - * eventFn : function(element, done) { - * //code to run the animation - * //once complete, then run done() - * return function cancellationFunction() { - * //code to cancel the animation - * } - * } - * } + * //enter, leave, move signature + * eventFn : function(element, done, options) { + * //code to run the animation + * //once complete, then run done() + * return function endFunction(wasCancelled) { + * //code to cancel the animation + * } + * } + * } * ``` * - * @param {string} name The name of the animation. + * @param {string} name The name of the animation (this is what the class-based CSS value will be compared to). * @param {Function} factory The factory function that will be executed to return the animation * object. */ this.register = function(name, factory) { + if (name && name.charAt(0) !== '.') { + throw $animateMinErr('notcsel', "Expecting class selector starting with '.' got '{0}'.", name); + } + var key = name + '-animation'; - if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel', - "Expecting class selector starting with '.' got '{0}'.", name); - this.$$selectors[name.substr(1)] = key; + provider.$$registeredAnimations[name.substr(1)] = key; $provide.factory(key, factory); }; @@ -67,8 +220,8 @@ var $AnimateProvider = ['$provide', function($provide) { * @description * Sets and/or returns the CSS class regular expression that is checked when performing * an animation. Upon bootstrap the classNameFilter value is not set at all and will - * therefore enable $animate to attempt to perform an animation on any element. - * When setting the classNameFilter value, animations will only be performed on elements + * therefore enable $animate to attempt to perform an animation on any element that is triggered. + * When setting the `classNameFilter` value, animations will only be performed on elements * that successfully match the filter expression. This in turn can boost performance * for low-powered devices as well as applications containing a lot of structural operations. * @param {RegExp=} expression The className expression which will be checked against all animations @@ -81,98 +234,48 @@ var $AnimateProvider = ['$provide', function($provide) { return this.$$classNameFilter; }; - this.$get = ['$$q', '$$asyncCallback', '$rootScope', function($$q, $$asyncCallback, $rootScope) { - - var currentDefer; - - function runAnimationPostDigest(fn) { - var cancelFn, defer = $$q.defer(); - defer.promise.$$cancelFn = function ngAnimateMaybeCancel() { - cancelFn && cancelFn(); - }; - - $rootScope.$$postDigest(function ngAnimatePostDigest() { - cancelFn = fn(function ngAnimateNotifyComplete() { - defer.resolve(); - }); - }); - - return defer.promise; - } - - function resolveElementClasses(element, classes) { - var toAdd = [], toRemove = []; - - var hasClasses = createMap(); - forEach((element.attr('class') || '').split(/\s+/), function(className) { - hasClasses[className] = true; - }); - - forEach(classes, function(status, className) { - var hasClass = hasClasses[className]; - - // If the most recent class manipulation (via $animate) was to remove the class, and the - // element currently has the class, the class is scheduled for removal. Otherwise, if - // the most recent class manipulation (via $animate) was to add the class, and the - // element does not currently have the class, the class is scheduled to be added. - if (status === false && hasClass) { - toRemove.push(className); - } else if (status === true && !hasClass) { - toAdd.push(className); + this.$get = ['$$animateQueue', function($$animateQueue) { + function domInsert(element, parentElement, afterElement) { + // if for some reason the previous element was removed + // from the dom sometime before this code runs then let's + // just stick to using the parent element as the anchor + if (afterElement) { + var afterNode = extractElementNode(afterElement); + if (afterNode && !afterNode.parentNode && !afterNode.previousElementSibling) { + afterElement = null; } - }); - - return (toAdd.length + toRemove.length) > 0 && - [toAdd.length ? toAdd : null, toRemove.length ? toRemove : null]; - } - - function cachedClassManipulation(cache, classes, op) { - for (var i=0, ii = classes.length; i < ii; ++i) { - var className = classes[i]; - cache[className] = op; - } - } - - function asyncPromise() { - // only serve one instance of a promise in order to save CPU cycles - if (!currentDefer) { - currentDefer = $$q.defer(); - $$asyncCallback(function() { - currentDefer.resolve(); - currentDefer = null; - }); - } - return currentDefer.promise; - } - - function applyStyles(element, options) { - if (angular.isObject(options)) { - var styles = extend(options.from || {}, options.to || {}); - element.css(styles); } + afterElement ? afterElement.after(element) : parentElement.prepend(element); } /** - * * @ngdoc service * @name $animate - * @description The $animate service provides rudimentary DOM manipulation functions to - * insert, remove and move elements within the DOM, as well as adding and removing classes. - * This service is the core service used by the ngAnimate $animator service which provides - * high-level animation hooks for CSS and JavaScript. + * @description The $animate service exposes a series of DOM utility methods that provide support + * for animation hooks. The default behavior is the application of DOM operations, however, + * when an animation is detected (and animations are enabled), $animate will do the heavy lifting + * to ensure that animation runs with the triggered DOM operation. + * + * By default $animate doesn't trigger an animations. This is because the `ngAnimate` module isn't + * included and only when it is active then the animation hooks that `$animate` triggers will be + * functional. Once active then all structural `ng-` directives will trigger animations as they perform + * their DOM-related operations (enter, leave and move). Other directives such as `ngClass`, + * `ngShow`, `ngHide` and `ngMessages` also provide support for animations. * - * $animate is available in the AngularJS core, however, the ngAnimate module must be included - * to enable full out animation support. Otherwise, $animate will only perform simple DOM - * manipulation operations. + * It is recommended that the`$animate` service is always used when executing DOM-related procedures within directives. * - * To learn more about enabling animation support, click here to visit the {@link ngAnimate - * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service - * page}. + * To learn more about enabling animation support, click here to visit the + * {@link ngAnimate ngAnimate module page}. */ return { - animate: function(element, from, to) { - applyStyles(element, { from: from, to: to }); - return asyncPromise(); + // we don't call it directly since non-existant arguments may + // be interpreted as null within the sub enabled function + on: $$animateQueue.on, + off: $$animateQueue.off, + enabled: $$animateQueue.enabled, + + cancel: function(runner) { + runner.cancel && runner.end(); }, /** @@ -180,193 +283,172 @@ var $AnimateProvider = ['$provide', function($provide) { * @ngdoc method * @name $animate#enter * @kind function - * @description Inserts the element into the DOM either after the `after` element or - * as the first child within the `parent` element. When the function is called a promise - * is returned that will be resolved at a later time. + * @description Inserts the element into the DOM either after the `after` element (if provided) or + * as the first child within the `parent` element and then triggers an animation. + * A promise is returned that will be resolved during the next digest once the animation + * has completed. + * * @param {DOMElement} element the element which will be inserted into the DOM * @param {DOMElement} parent the parent element which will append the element as - * a child (if the after element is not present) - * @param {DOMElement} after the sibling element which will append the element - * after itself - * @param {object=} options an optional collection of styles that will be applied to the element. + * a child (so long as the after element is not present) + * @param {DOMElement=} after the sibling element after which the element will be appended + * @param {object=} options an optional collection of options/styles that will be applied to the element + * * @return {Promise} the animation callback promise */ enter: function(element, parent, after, options) { - applyStyles(element, options); - after ? after.after(element) - : parent.prepend(element); - return asyncPromise(); + parent = parent || after.parent(); + domInsert(element, parent, after); + return $$animateQueue.push(element, 'enter', options); }, /** * * @ngdoc method - * @name $animate#leave + * @name $animate#move * @kind function - * @description Removes the element from the DOM. When the function is called a promise - * is returned that will be resolved at a later time. - * @param {DOMElement} element the element which will be removed from the DOM - * @param {object=} options an optional collection of options that will be applied to the element. + * @description Inserts (moves) the element into its new position in the DOM either after + * the `after` element (if provided) or as the first child within the `parent` element + * and then triggers an animation. A promise is returned that will be resolved + * during the next digest once the animation has completed. + * + * @param {DOMElement} element the element which will be moved into the new DOM position + * @param {DOMElement} parent the parent element which will append the element as + * a child (so long as the after element is not present) + * @param {DOMElement=} after the sibling element after which the element will be appended + * @param {object=} options an optional collection of options/styles that will be applied to the element + * * @return {Promise} the animation callback promise */ - leave: function(element, options) { - applyStyles(element, options); - element.remove(); - return asyncPromise(); + move: function(element, parent, after, options) { + parent = parent || after.parent(); + domInsert(element, parent, after); + return $$animateQueue.push(element, 'move', options); }, /** - * * @ngdoc method - * @name $animate#move + * @name $animate#leave * @kind function - * @description Moves the position of the provided element within the DOM to be placed - * either after the `after` element or inside of the `parent` element. When the function - * is called a promise is returned that will be resolved at a later time. + * @description Triggers an animation and then removes the element from the DOM. + * When the function is called a promise is returned that will be resolved during the next + * digest once the animation has completed. + * + * @param {DOMElement} element the element which will be removed from the DOM + * @param {object=} options an optional collection of options/styles that will be applied to the element * - * @param {DOMElement} element the element which will be moved around within the - * DOM - * @param {DOMElement} parent the parent element where the element will be - * inserted into (if the after element is not present) - * @param {DOMElement} after the sibling element where the element will be - * positioned next to - * @param {object=} options an optional collection of options that will be applied to the element. * @return {Promise} the animation callback promise */ - move: function(element, parent, after, options) { - // Do not remove element before insert. Removing will cause data associated with the - // element to be dropped. Insert will implicitly do the remove. - return this.enter(element, parent, after, options); + leave: function(element, options) { + return $$animateQueue.push(element, 'leave', options, function() { + element.remove(); + }); }, /** - * * @ngdoc method * @name $animate#addClass * @kind function - * @description Adds the provided className CSS class value to the provided element. - * When the function is called a promise is returned that will be resolved at a later time. - * @param {DOMElement} element the element which will have the className value - * added to it - * @param {string} className the CSS class which will be added to the element - * @param {object=} options an optional collection of options that will be applied to the element. + * + * @description Triggers an addClass animation surrounding the addition of the provided CSS class(es). Upon + * execution, the addClass operation will only be handled after the next digest and it will not trigger an + * animation if element already contains the CSS class or if the class is removed at a later step. + * Note that class-based animations are treated differently compared to structural animations + * (like enter, move and leave) since the CSS classes may be added/removed at different points + * depending if CSS or JavaScript animations are used. + * + * @param {DOMElement} element the element which the CSS classes will be applied to + * @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces) + * @param {object=} options an optional collection of options/styles that will be applied to the element + * * @return {Promise} the animation callback promise */ addClass: function(element, className, options) { - return this.setClass(element, className, [], options); - }, - - $$addClassImmediately: function(element, className, options) { - element = jqLite(element); - className = !isString(className) - ? (isArray(className) ? className.join(' ') : '') - : className; - forEach(element, function(element) { - jqLiteAddClass(element, className); - }); - applyStyles(element, options); - return asyncPromise(); + options = options || {}; + options.addClass = mergeClasses(options.addclass, className); + return $$animateQueue.push(element, 'addClass', options); }, /** - * * @ngdoc method * @name $animate#removeClass * @kind function - * @description Removes the provided className CSS class value from the provided element. - * When the function is called a promise is returned that will be resolved at a later time. - * @param {DOMElement} element the element which will have the className value - * removed from it - * @param {string} className the CSS class which will be removed from the element - * @param {object=} options an optional collection of options that will be applied to the element. + * + * @description Triggers a removeClass animation surrounding the removal of the provided CSS class(es). Upon + * execution, the removeClass operation will only be handled after the next digest and it will not trigger an + * animation if element does not contain the CSS class or if the class is added at a later step. + * Note that class-based animations are treated differently compared to structural animations + * (like enter, move and leave) since the CSS classes may be added/removed at different points + * depending if CSS or JavaScript animations are used. + * + * @param {DOMElement} element the element which the CSS classes will be applied to + * @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces) + * @param {object=} options an optional collection of options/styles that will be applied to the element + * * @return {Promise} the animation callback promise */ removeClass: function(element, className, options) { - return this.setClass(element, [], className, options); - }, - - $$removeClassImmediately: function(element, className, options) { - element = jqLite(element); - className = !isString(className) - ? (isArray(className) ? className.join(' ') : '') - : className; - forEach(element, function(element) { - jqLiteRemoveClass(element, className); - }); - applyStyles(element, options); - return asyncPromise(); + options = options || {}; + options.removeClass = mergeClasses(options.removeClass, className); + return $$animateQueue.push(element, 'removeClass', options); }, /** - * * @ngdoc method * @name $animate#setClass * @kind function - * @description Adds and/or removes the given CSS classes to and from the element. - * When the function is called a promise is returned that will be resolved at a later time. - * @param {DOMElement} element the element which will have its CSS classes changed - * removed from it - * @param {string} add the CSS classes which will be added to the element - * @param {string} remove the CSS class which will be removed from the element - * @param {object=} options an optional collection of options that will be applied to the element. + * + * @description Performs both the addition and removal of a CSS classes on an element and (during the process) + * triggers an animation surrounding the class addition/removal. Much like `$animate.addClass` and + * `$animate.removeClass`, `setClass` will only evaluate the classes being added/removed once a digest has + * passed. Note that class-based animations are treated differently compared to structural animations + * (like enter, move and leave) since the CSS classes may be added/removed at different points + * depending if CSS or JavaScript animations are used. + * + * @param {DOMElement} element the element which the CSS classes will be applied to + * @param {string} add the CSS class(es) that will be added (multiple classes are separated via spaces) + * @param {string} remove the CSS class(es) that will be removed (multiple classes are separated via spaces) + * @param {object=} options an optional collection of options/styles that will be applied to the element + * * @return {Promise} the animation callback promise */ setClass: function(element, add, remove, options) { - var self = this; - var STORAGE_KEY = '$$animateClasses'; - var createdCache = false; - element = jqLite(element); - - var cache = element.data(STORAGE_KEY); - if (!cache) { - cache = { - classes: {}, - options: options - }; - createdCache = true; - } else if (options && cache.options) { - cache.options = angular.extend(cache.options || {}, options); - } - - var classes = cache.classes; - - add = isArray(add) ? add : add.split(' '); - remove = isArray(remove) ? remove : remove.split(' '); - cachedClassManipulation(classes, add, true); - cachedClassManipulation(classes, remove, false); - - if (createdCache) { - cache.promise = runAnimationPostDigest(function(done) { - var cache = element.data(STORAGE_KEY); - element.removeData(STORAGE_KEY); - - // in the event that the element is removed before postDigest - // is run then the cache will be undefined and there will be - // no need anymore to add or remove and of the element classes - if (cache) { - var classes = resolveElementClasses(element, cache.classes); - if (classes) { - self.$$setClassImmediately(element, classes[0], classes[1], cache.options); - } - } - - done(); - }); - element.data(STORAGE_KEY, cache); - } - - return cache.promise; - }, - - $$setClassImmediately: function(element, add, remove, options) { - add && this.$$addClassImmediately(element, add); - remove && this.$$removeClassImmediately(element, remove); - applyStyles(element, options); - return asyncPromise(); + options = options || {}; + options.addClass = mergeClasses(options.addClass, add); + options.removeClass = mergeClasses(options.removeClass, remove); + return $$animateQueue.push(element, 'setClass', options); }, - enabled: noop, - cancel: noop + /** + * @ngdoc method + * @name $animate#animate + * @kind function + * + * @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element. + * If any detected CSS transition, keyframe or JavaScript matches the provided className value then the animation will take + * on the provided styles. For example, if a transition animation is set for the given className then the provided from and + * to styles will be applied alongside the given transition. If a JavaScript animation is detected then the provided styles + * will be given in as function paramters into the `animate` method (or as apart of the `options` parameter). + * + * @param {DOMElement} element the element which the CSS styles will be applied to + * @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation. + * @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation. + * @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If + * this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element. + * (Note that if no animation is detected then this value will not be appplied to the element.) + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + animate: function(element, from, to, className, options) { + options = options || {}; + options.from = options.from ? extend(options.from, from) : from; + options.to = options.to ? extend(options.to, to) : to; + + className = className || 'ng-inline-animate'; + options.tempClasses = mergeClasses(options.tempClasses, className); + return $$animateQueue.push(element, 'animate', options); + } }; }]; }]; diff --git a/src/ng/directive/ngClass.js b/src/ng/directive/ngClass.js index 3616c5ebf072..af8d07388cd7 100644 --- a/src/ng/directive/ngClass.js +++ b/src/ng/directive/ngClass.js @@ -275,8 +275,8 @@ function classDirective(name, selector) { The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure. Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure - to view the step by step details of {@link ng.$animate#addClass $animate.addClass} and - {@link ng.$animate#removeClass $animate.removeClass}. + to view the step by step details of {@link $animate#addClass $animate.addClass} and + {@link $animate#removeClass $animate.removeClass}. */ var ngClassDirective = classDirective('', true); diff --git a/src/ngAnimate/.jshintrc b/src/ngAnimate/.jshintrc index b738582198ed..c6a112ff0f22 100644 --- a/src/ngAnimate/.jshintrc +++ b/src/ngAnimate/.jshintrc @@ -1,8 +1,40 @@ { "extends": "../../.jshintrc-base", "maxlen": false, /* ngAnimate docs contain wide tables */ + "newcap": false, "browser": true, "globals": { - "angular": false + "angular": false, + "noop": false, + + "forEach": false, + "extend": false, + "jqLite": false, + "forEach": false, + "isArray": false, + "isString": false, + "isObject": false, + "isUndefined": false, + "isDefined": false, + "isFunction": false, + "isElement": false, + + "ELEMENT_NODE": false, + "NG_ANIMATE_CHILDREN_DATA": false, + + "isPromiseLike": false, + "mergeClasses": false, + "mergeAnimationOptions": false, + "prepareAnimationOptions": false, + "applyAnimationStyles": false, + "applyAnimationFromStyles": false, + "applyAnimationToStyles": false, + "applyAnimationClassesFactory": false, + "pendClasses": false, + "normalizeCssProp": false, + "packageStyles": false, + "removeFromArray": false, + "stripCommentsFromElement": false, + "extractElementNode": false } -} \ No newline at end of file +} diff --git a/src/ngAnimate/animate.js b/src/ngAnimate/animate.js deleted file mode 100644 index b87ed335cb2b..000000000000 --- a/src/ngAnimate/animate.js +++ /dev/null @@ -1,2130 +0,0 @@ -'use strict'; -/* jshint maxlen: false */ - -/** - * @ngdoc module - * @name ngAnimate - * @description - * - * The `ngAnimate` module provides support for JavaScript, CSS3 transition and CSS3 keyframe animation hooks within existing core and custom directives. - * - *
- * - * # Usage - * - * To see animations in action, all that is required is to define the appropriate CSS classes - * or to register a JavaScript animation via the `myModule.animation()` function. The directives that support animation automatically are: - * `ngRepeat`, `ngInclude`, `ngIf`, `ngSwitch`, `ngShow`, `ngHide`, `ngView` and `ngClass`. Custom directives can take advantage of animation - * by using the `$animate` service. - * - * Below is a more detailed breakdown of the supported animation events provided by pre-existing ng directives: - * - * | Directive | Supported Animations | - * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------| - * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move | - * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave | - * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave | - * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave | - * | {@link ng.directive:ngIf#animations ngIf} | enter and leave | - * | {@link ng.directive:ngClass#animations ngClass} | add and remove (the CSS class(es) present) | - * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide} | add and remove (the ng-hide class value) | - * | {@link ng.directive:form#animation-hooks form} & {@link ng.directive:ngModel#animation-hooks ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) | - * | {@link module:ngMessages#animations ngMessages} | add and remove (ng-active & ng-inactive) | - * | {@link module:ngMessages#animations ngMessage} | enter and leave | - * - * You can find out more information about animations upon visiting each directive page. - * - * Below is an example of how to apply animations to a directive that supports animation hooks: - * - * ```html - * - * - * - * - * ``` - * - * Keep in mind that, by default, if an animation is running, any child elements cannot be animated - * until the parent element's animation has completed. This blocking feature can be overridden by - * placing the `ng-animate-children` attribute on a parent container tag. - * - * ```html - *
- *
- *
- * ... - *
- *
- *
- * ``` - * - * When the `on` expression value changes and an animation is triggered then each of the elements within - * will all animate without the block being applied to child elements. - * - * ## Are animations run when the application starts? - * No they are not. When an application is bootstrapped Angular will disable animations from running to avoid - * a frenzy of animations from being triggered as soon as the browser has rendered the screen. For this to work, - * Angular will wait for two digest cycles until enabling animations. From there on, any animation-triggering - * layout changes in the application will trigger animations as normal. - * - * In addition, upon bootstrap, if the routing system or any directives or load remote data (via $http) then Angular - * will automatically extend the wait time to enable animations once **all** of the outbound HTTP requests - * are complete. - * - * ## CSS-defined Animations - * The animate service will automatically apply two CSS classes to the animated element and these two CSS classes - * are designed to contain the start and end CSS styling. Both CSS transitions and keyframe animations are supported - * and can be used to play along with this naming structure. - * - * The following code below demonstrates how to perform animations using **CSS transitions** with Angular: - * - * ```html - * - * - *
- *
- *
- * ``` - * - * The following code below demonstrates how to perform animations using **CSS animations** with Angular: - * - * ```html - * - * - *
- *
- *
- * ``` - * - * Both CSS3 animations and transitions can be used together and the animate service will figure out the correct duration and delay timing. - * - * Upon DOM mutation, the event class is added first (something like `ng-enter`), then the browser prepares itself to add - * the active class (in this case `ng-enter-active`) which then triggers the animation. The animation module will automatically - * detect the CSS code to determine when the animation ends. Once the animation is over then both CSS classes will be - * removed from the DOM. If a browser does not support CSS transitions or CSS animations then the animation will start and end - * immediately resulting in a DOM element that is at its final state. This final state is when the DOM element - * has no CSS transition/animation classes applied to it. - * - * ### Structural transition animations - * - * Structural transitions (such as enter, leave and move) will always apply a `0s none` transition - * value to force the browser into rendering the styles defined in the setup (`.ng-enter`, `.ng-leave` - * or `.ng-move`) class. This means that any active transition animations operating on the element - * will be cut off to make way for the enter, leave or move animation. - * - * ### Class-based transition animations - * - * Class-based transitions refer to transition animations that are triggered when a CSS class is - * added to or removed from the element (via `$animate.addClass`, `$animate.removeClass`, - * `$animate.setClass`, or by directives such as `ngClass`, `ngModel` and `form`). - * They are different when compared to structural animations since they **do not cancel existing - * animations** nor do they **block successive transitions** from rendering on the same element. - * This distinction allows for **multiple class-based transitions** to be performed on the same element. - * - * In addition to ngAnimate supporting the default (natural) functionality of class-based transition - * animations, ngAnimate also decorates the element with starting and ending CSS classes to aid the - * developer in further styling the element throughout the transition animation. Earlier versions - * of ngAnimate may have caused natural CSS transitions to break and not render properly due to - * $animate temporarily blocking transitions using `0s none` in order to allow the setup CSS class - * (the `-add` or `-remove` class) to be applied without triggering an animation. However, as of - * **version 1.3**, this workaround has been removed with ngAnimate and all non-ngAnimate CSS - * class transitions are compatible with ngAnimate. - * - * There is, however, one special case when dealing with class-based transitions in ngAnimate. - * When rendering class-based transitions that make use of the setup and active CSS classes - * (e.g. `.fade-add` and `.fade-add-active` for when `.fade` is added) be sure to define - * the transition value **on the active CSS class** and not the setup class. - * - * ```css - * .fade-add { - * /* remember to place a 0s transition here - * to ensure that the styles are applied instantly - * even if the element already has a transition style */ - * transition:0s linear all; - * - * /* starting CSS styles */ - * opacity:1; - * } - * .fade-add.fade-add-active { - * /* this will be the length of the animation */ - * transition:1s linear all; - * opacity:0; - * } - * ``` - * - * The setup CSS class (in this case `.fade-add`) also has a transition style property, however, it - * has a duration of zero. This may not be required, however, incase the browser is unable to render - * the styling present in this CSS class instantly then it could be that the browser is attempting - * to perform an unnecessary transition. - * - * This workaround, however, does not apply to standard class-based transitions that are rendered - * when a CSS class containing a transition is applied to an element: - * - * ```css - * /* this works as expected */ - * .fade { - * transition:1s linear all; - * opacity:0; - * } - * ``` - * - * Please keep this in mind when coding the CSS markup that will be used within class-based transitions. - * Also, try not to mix the two class-based animation flavors together since the CSS code may become - * overly complex. - * - * - * ### Preventing Collisions With Third Party Libraries - * - * Some third-party frameworks place animation duration defaults across many element or className - * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which - * is expecting actual animations on these elements and has to wait for their completion. - * - * You can prevent this unwanted behavior by using a prefix on all your animation classes: - * - * ```css - * /* prefixed with animate- */ - * .animate-fade-add.animate-fade-add-active { - * transition:1s linear all; - * opacity:0; - * } - * ``` - * - * You then configure `$animate` to enforce this prefix: - * - * ```js - * $animateProvider.classNameFilter(/animate-/); - * ``` - *
- * - * ### CSS Staggering Animations - * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a - * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be - * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for - * the animation. The style property expected within the stagger class can either be a **transition-delay** or an - * **animation-delay** property (or both if your animation contains both transitions and keyframe animations). - * - * ```css - * .my-animation.ng-enter { - * /* standard transition code */ - * -webkit-transition: 1s linear all; - * transition: 1s linear all; - * opacity:0; - * } - * .my-animation.ng-enter-stagger { - * /* this will have a 100ms delay between each successive leave animation */ - * -webkit-transition-delay: 0.1s; - * transition-delay: 0.1s; - * - * /* in case the stagger doesn't work then these two values - * must be set to 0 to avoid an accidental CSS inheritance */ - * -webkit-transition-duration: 0s; - * transition-duration: 0s; - * } - * .my-animation.ng-enter.ng-enter-active { - * /* standard transition styles */ - * opacity:1; - * } - * ``` - * - * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations - * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this - * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation - * will also be reset if more than 10ms has passed after the last animation has been fired. - * - * The following code will issue the **ng-leave-stagger** event on the element provided: - * - * ```js - * var kids = parent.children(); - * - * $animate.leave(kids[0]); //stagger index=0 - * $animate.leave(kids[1]); //stagger index=1 - * $animate.leave(kids[2]); //stagger index=2 - * $animate.leave(kids[3]); //stagger index=3 - * $animate.leave(kids[4]); //stagger index=4 - * - * $timeout(function() { - * //stagger has reset itself - * $animate.leave(kids[5]); //stagger index=0 - * $animate.leave(kids[6]); //stagger index=1 - * }, 100, false); - * ``` - * - * Stagger animations are currently only supported within CSS-defined animations. - * - * ## JavaScript-defined Animations - * In the event that you do not want to use CSS3 transitions or CSS3 animations or if you wish to offer animations on browsers that do not - * yet support CSS transitions/animations, then you can make use of JavaScript animations defined inside of your AngularJS module. - * - * ```js - * //!annotate="YourApp" Your AngularJS Module|Replace this or ngModule with the module that you used to define your application. - * var ngModule = angular.module('YourApp', ['ngAnimate']); - * ngModule.animation('.my-crazy-animation', function() { - * return { - * enter: function(element, done) { - * //run the animation here and call done when the animation is complete - * return function(cancelled) { - * //this (optional) function will be called when the animation - * //completes or when the animation is cancelled (the cancelled - * //flag will be set to true if cancelled). - * }; - * }, - * leave: function(element, done) { }, - * move: function(element, done) { }, - * - * //animation that can be triggered before the class is added - * beforeAddClass: function(element, className, done) { }, - * - * //animation that can be triggered after the class is added - * addClass: function(element, className, done) { }, - * - * //animation that can be triggered before the class is removed - * beforeRemoveClass: function(element, className, done) { }, - * - * //animation that can be triggered after the class is removed - * removeClass: function(element, className, done) { } - * }; - * }); - * ``` - * - * JavaScript-defined animations are created with a CSS-like class selector and a collection of events which are set to run - * a javascript callback function. When an animation is triggered, $animate will look for a matching animation which fits - * the element's CSS class attribute value and then run the matching animation event function (if found). - * In other words, if the CSS classes present on the animated element match any of the JavaScript animations then the callback function will - * be executed. It should be also noted that only simple, single class selectors are allowed (compound class selectors are not supported). - * - * Within a JavaScript animation, an object containing various event callback animation functions is expected to be returned. - * As explained above, these callbacks are triggered based on the animation event. Therefore if an enter animation is run, - * and the JavaScript animation is found, then the enter callback will handle that animation (in addition to the CSS keyframe animation - * or transition code that is defined via a stylesheet). - * - * - * ### Applying Directive-specific Styles to an Animation - * In some cases a directive or service may want to provide `$animate` with extra details that the animation will - * include into its animation. Let's say for example we wanted to render an animation that animates an element - * towards the mouse coordinates as to where the user clicked last. By collecting the X/Y coordinates of the click - * (via the event parameter) we can set the `top` and `left` styles into an object and pass that into our function - * call to `$animate.addClass`. - * - * ```js - * canvas.on('click', function(e) { - * $animate.addClass(element, 'on', { - * to: { - * left : e.client.x + 'px', - * top : e.client.y + 'px' - * } - * }): - * }); - * ``` - * - * Now when the animation runs, and a transition or keyframe animation is picked up, then the animation itself will - * also include and transition the styling of the `left` and `top` properties into its running animation. If we want - * to provide some starting animation values then we can do so by placing the starting animations styles into an object - * called `from` in the same object as the `to` animations. - * - * ```js - * canvas.on('click', function(e) { - * $animate.addClass(element, 'on', { - * from: { - * position: 'absolute', - * left: '0px', - * top: '0px' - * }, - * to: { - * left : e.client.x + 'px', - * top : e.client.y + 'px' - * } - * }): - * }); - * ``` - * - * Once the animation is complete or cancelled then the union of both the before and after styles are applied to the - * element. If `ngAnimate` is not present then the styles will be applied immediately. - * - */ - -angular.module('ngAnimate', ['ng']) - - /** - * @ngdoc provider - * @name $animateProvider - * @description - * - * The `$animateProvider` allows developers to register JavaScript animation event handlers directly inside of a module. - * When an animation is triggered, the $animate service will query the $animate service to find any animations that match - * the provided name value. - * - * Requires the {@link ngAnimate `ngAnimate`} module to be installed. - * - * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application. - * - */ - .directive('ngAnimateChildren', function() { - var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren'; - return function(scope, element, attrs) { - var val = attrs.ngAnimateChildren; - if (angular.isString(val) && val.length === 0) { //empty attribute - element.data(NG_ANIMATE_CHILDREN, true); - } else { - scope.$watch(val, function(value) { - element.data(NG_ANIMATE_CHILDREN, !!value); - }); - } - }; - }) - - //this private service is only used within CSS-enabled animations - //IE8 + IE9 do not support rAF natively, but that is fine since they - //also don't support transitions and keyframes which means that the code - //below will never be used by the two browsers. - .factory('$$animateReflow', ['$$rAF', '$document', function($$rAF, $document) { - var bod = $document[0].body; - return function(fn) { - //the returned function acts as the cancellation function - return $$rAF(function() { - //the line below will force the browser to perform a repaint - //so that all the animated elements within the animation frame - //will be properly updated and drawn on screen. This is - //required to perform multi-class CSS based animations with - //Firefox. DO NOT REMOVE THIS LINE. DO NOT OPTIMIZE THIS LINE. - //THE MINIFIER WILL REMOVE IT OTHERWISE WHICH WILL RESULT IN AN - //UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND WILL - //TAKE YEARS AWAY FROM YOUR LIFE! - fn(bod.offsetWidth); - }); - }; - }]) - - .config(['$provide', '$animateProvider', function($provide, $animateProvider) { - var noop = angular.noop; - var forEach = angular.forEach; - var selectors = $animateProvider.$$selectors; - var isArray = angular.isArray; - var isString = angular.isString; - var isObject = angular.isObject; - - var ELEMENT_NODE = 1; - var NG_ANIMATE_STATE = '$$ngAnimateState'; - var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren'; - var NG_ANIMATE_CLASS_NAME = 'ng-animate'; - var rootAnimateState = {running: true}; - - function extractElementNode(element) { - for (var i = 0; i < element.length; i++) { - var elm = element[i]; - if (elm.nodeType == ELEMENT_NODE) { - return elm; - } - } - } - - function prepareElement(element) { - return element && angular.element(element); - } - - function stripCommentsFromElement(element) { - return angular.element(extractElementNode(element)); - } - - function isMatchingElement(elm1, elm2) { - return extractElementNode(elm1) == extractElementNode(elm2); - } - var $$jqLite; - $provide.decorator('$animate', - ['$delegate', '$$q', '$injector', '$sniffer', '$rootElement', '$$asyncCallback', '$rootScope', '$document', '$templateRequest', '$$jqLite', - function($delegate, $$q, $injector, $sniffer, $rootElement, $$asyncCallback, $rootScope, $document, $templateRequest, $$$jqLite) { - - $$jqLite = $$$jqLite; - $rootElement.data(NG_ANIMATE_STATE, rootAnimateState); - - // Wait until all directive and route-related templates are downloaded and - // compiled. The $templateRequest.totalPendingRequests variable keeps track of - // all of the remote templates being currently downloaded. If there are no - // templates currently downloading then the watcher will still fire anyway. - var deregisterWatch = $rootScope.$watch( - function() { return $templateRequest.totalPendingRequests; }, - function(val, oldVal) { - if (val !== 0) return; - deregisterWatch(); - - // Now that all templates have been downloaded, $animate will wait until - // the post digest queue is empty before enabling animations. By having two - // calls to $postDigest calls we can ensure that the flag is enabled at the - // very end of the post digest queue. Since all of the animations in $animate - // use $postDigest, it's important that the code below executes at the end. - // This basically means that the page is fully downloaded and compiled before - // any animations are triggered. - $rootScope.$$postDigest(function() { - $rootScope.$$postDigest(function() { - rootAnimateState.running = false; - }); - }); - } - ); - - var globalAnimationCounter = 0; - var classNameFilter = $animateProvider.classNameFilter(); - var isAnimatableClassName = !classNameFilter - ? function() { return true; } - : function(className) { - return classNameFilter.test(className); - }; - - function classBasedAnimationsBlocked(element, setter) { - var data = element.data(NG_ANIMATE_STATE) || {}; - if (setter) { - data.running = true; - data.structural = true; - element.data(NG_ANIMATE_STATE, data); - } - return data.disabled || (data.running && data.structural); - } - - function runAnimationPostDigest(fn) { - var cancelFn, defer = $$q.defer(); - defer.promise.$$cancelFn = function() { - cancelFn && cancelFn(); - }; - $rootScope.$$postDigest(function() { - cancelFn = fn(function() { - defer.resolve(); - }); - }); - return defer.promise; - } - - function parseAnimateOptions(options) { - // some plugin code may still be passing in the callback - // function as the last param for the $animate methods so - // it's best to only allow string or array values for now - if (isObject(options)) { - if (options.tempClasses && isString(options.tempClasses)) { - options.tempClasses = options.tempClasses.split(/\s+/); - } - return options; - } - } - - function resolveElementClasses(element, cache, runningAnimations) { - runningAnimations = runningAnimations || {}; - - var lookup = {}; - forEach(runningAnimations, function(data, selector) { - forEach(selector.split(' '), function(s) { - lookup[s]=data; - }); - }); - - var hasClasses = Object.create(null); - forEach((element.attr('class') || '').split(/\s+/), function(className) { - hasClasses[className] = true; - }); - - var toAdd = [], toRemove = []; - forEach((cache && cache.classes) || [], function(status, className) { - var hasClass = hasClasses[className]; - var matchingAnimation = lookup[className] || {}; - - // When addClass and removeClass is called then $animate will check to - // see if addClass and removeClass cancel each other out. When there are - // more calls to removeClass than addClass then the count falls below 0 - // and then the removeClass animation will be allowed. Otherwise if the - // count is above 0 then that means an addClass animation will commence. - // Once an animation is allowed then the code will also check to see if - // there exists any on-going animation that is already adding or remvoing - // the matching CSS class. - if (status === false) { - //does it have the class or will it have the class - if (hasClass || matchingAnimation.event == 'addClass') { - toRemove.push(className); - } - } else if (status === true) { - //is the class missing or will it be removed? - if (!hasClass || matchingAnimation.event == 'removeClass') { - toAdd.push(className); - } - } - }); - - return (toAdd.length + toRemove.length) > 0 && [toAdd.join(' '), toRemove.join(' ')]; - } - - function lookup(name) { - if (name) { - var matches = [], - flagMap = {}, - classes = name.substr(1).split('.'); - - //the empty string value is the default animation - //operation which performs CSS transition and keyframe - //animations sniffing. This is always included for each - //element animation procedure if the browser supports - //transitions and/or keyframe animations. The default - //animation is added to the top of the list to prevent - //any previous animations from affecting the element styling - //prior to the element being animated. - if ($sniffer.transitions || $sniffer.animations) { - matches.push($injector.get(selectors[''])); - } - - for (var i=0; i < classes.length; i++) { - var klass = classes[i], - selectorFactoryName = selectors[klass]; - if (selectorFactoryName && !flagMap[klass]) { - matches.push($injector.get(selectorFactoryName)); - flagMap[klass] = true; - } - } - return matches; - } - } - - function animationRunner(element, animationEvent, className, options) { - //transcluded directives may sometimes fire an animation using only comment nodes - //best to catch this early on to prevent any animation operations from occurring - var node = element[0]; - if (!node) { - return; - } - - if (options) { - options.to = options.to || {}; - options.from = options.from || {}; - } - - var classNameAdd; - var classNameRemove; - if (isArray(className)) { - classNameAdd = className[0]; - classNameRemove = className[1]; - if (!classNameAdd) { - className = classNameRemove; - animationEvent = 'removeClass'; - } else if (!classNameRemove) { - className = classNameAdd; - animationEvent = 'addClass'; - } else { - className = classNameAdd + ' ' + classNameRemove; - } - } - - var isSetClassOperation = animationEvent == 'setClass'; - var isClassBased = isSetClassOperation - || animationEvent == 'addClass' - || animationEvent == 'removeClass' - || animationEvent == 'animate'; - - var currentClassName = element.attr('class'); - var classes = currentClassName + ' ' + className; - if (!isAnimatableClassName(classes)) { - return; - } - - var beforeComplete = noop, - beforeCancel = [], - before = [], - afterComplete = noop, - afterCancel = [], - after = []; - - var animationLookup = (' ' + classes).replace(/\s+/g,'.'); - forEach(lookup(animationLookup), function(animationFactory) { - var created = registerAnimation(animationFactory, animationEvent); - if (!created && isSetClassOperation) { - registerAnimation(animationFactory, 'addClass'); - registerAnimation(animationFactory, 'removeClass'); - } - }); - - function registerAnimation(animationFactory, event) { - var afterFn = animationFactory[event]; - var beforeFn = animationFactory['before' + event.charAt(0).toUpperCase() + event.substr(1)]; - if (afterFn || beforeFn) { - if (event == 'leave') { - beforeFn = afterFn; - //when set as null then animation knows to skip this phase - afterFn = null; - } - after.push({ - event: event, fn: afterFn - }); - before.push({ - event: event, fn: beforeFn - }); - return true; - } - } - - function run(fns, cancellations, allCompleteFn) { - var animations = []; - forEach(fns, function(animation) { - animation.fn && animations.push(animation); - }); - - var count = 0; - function afterAnimationComplete(index) { - if (cancellations) { - (cancellations[index] || noop)(); - if (++count < animations.length) return; - cancellations = null; - } - allCompleteFn(); - } - - //The code below adds directly to the array in order to work with - //both sync and async animations. Sync animations are when the done() - //operation is called right away. DO NOT REFACTOR! - forEach(animations, function(animation, index) { - var progress = function() { - afterAnimationComplete(index); - }; - switch (animation.event) { - case 'setClass': - cancellations.push(animation.fn(element, classNameAdd, classNameRemove, progress, options)); - break; - case 'animate': - cancellations.push(animation.fn(element, className, options.from, options.to, progress)); - break; - case 'addClass': - cancellations.push(animation.fn(element, classNameAdd || className, progress, options)); - break; - case 'removeClass': - cancellations.push(animation.fn(element, classNameRemove || className, progress, options)); - break; - default: - cancellations.push(animation.fn(element, progress, options)); - break; - } - }); - - if (cancellations && cancellations.length === 0) { - allCompleteFn(); - } - } - - return { - node: node, - event: animationEvent, - className: className, - isClassBased: isClassBased, - isSetClassOperation: isSetClassOperation, - applyStyles: function() { - if (options) { - element.css(angular.extend(options.from || {}, options.to || {})); - } - }, - before: function(allCompleteFn) { - beforeComplete = allCompleteFn; - run(before, beforeCancel, function() { - beforeComplete = noop; - allCompleteFn(); - }); - }, - after: function(allCompleteFn) { - afterComplete = allCompleteFn; - run(after, afterCancel, function() { - afterComplete = noop; - allCompleteFn(); - }); - }, - cancel: function() { - if (beforeCancel) { - forEach(beforeCancel, function(cancelFn) { - (cancelFn || noop)(true); - }); - beforeComplete(true); - } - if (afterCancel) { - forEach(afterCancel, function(cancelFn) { - (cancelFn || noop)(true); - }); - afterComplete(true); - } - } - }; - } - - /** - * @ngdoc service - * @name $animate - * @kind object - * - * @description - * The `$animate` service provides animation detection support while performing DOM operations (enter, leave and move) as well as during addClass and removeClass operations. - * When any of these operations are run, the $animate service - * will examine any JavaScript-defined animations (which are defined by using the $animateProvider provider object) - * as well as any CSS-defined animations against the CSS classes present on the element once the DOM operation is run. - * - * The `$animate` service is used behind the scenes with pre-existing directives and animation with these directives - * will work out of the box without any extra configuration. - * - * Requires the {@link ngAnimate `ngAnimate`} module to be installed. - * - * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application. - * ## Callback Promises - * With AngularJS 1.3, each of the animation methods, on the `$animate` service, return a promise when called. The - * promise itself is then resolved once the animation has completed itself, has been cancelled or has been - * skipped due to animations being disabled. (Note that even if the animation is cancelled it will still - * call the resolve function of the animation.) - * - * ```js - * $animate.enter(element, container).then(function() { - * //...this is called once the animation is complete... - * }); - * ``` - * - * Also note that, due to the nature of the callback promise, if any Angular-specific code (like changing the scope, - * location of the page, etc...) is executed within the callback promise then be sure to wrap the code using - * `$scope.$apply(...)`; - * - * ```js - * $animate.leave(element).then(function() { - * $scope.$apply(function() { - * $location.path('/new-page'); - * }); - * }); - * ``` - * - * An animation can also be cancelled by calling the `$animate.cancel(promise)` method with the provided - * promise that was returned when the animation was started. - * - * ```js - * var promise = $animate.addClass(element, 'super-long-animation'); - * promise.then(function() { - * //this will still be called even if cancelled - * }); - * - * element.on('click', function() { - * //tooo lazy to wait for the animation to end - * $animate.cancel(promise); - * }); - * ``` - * - * (Keep in mind that the promise cancellation is unique to `$animate` since promises in - * general cannot be cancelled.) - * - */ - return { - /** - * @ngdoc method - * @name $animate#animate - * @kind function - * - * @description - * Performs an inline animation on the element which applies the provided `to` and `from` CSS styles to the element. - * If any detected CSS transition, keyframe or JavaScript matches the provided `className` value then the animation - * will take on the provided styles. For example, if a transition animation is set for the given className then the - * provided `from` and `to` styles will be applied alongside the given transition. If a JavaScript animation is - * detected then the provided styles will be given in as function paramters. - * - * ```js - * ngModule.animation('.my-inline-animation', function() { - * return { - * animate : function(element, className, from, to, done) { - * //styles - * } - * } - * }); - * ``` - * - * Below is a breakdown of each step that occurs during the `animate` animation: - * - * | Animation Step | What the element class attribute looks like | - * |-----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------| - * | 1. `$animate.animate(...)` is called | `class="my-animation"` | - * | 2. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` | - * | 3. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` | - * | 4. the `className` class value is added to the element | `class="my-animation ng-animate className"` | - * | 5. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate className"` | - * | 6. `$animate` blocks all CSS transitions on the element to ensure the `.className` class styling is applied right away| `class="my-animation ng-animate className"` | - * | 7. `$animate` applies the provided collection of `from` CSS styles to the element | `class="my-animation ng-animate className"` | - * | 8. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate className"` | - * | 9. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate className"` | - * | 10. the `className-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate className className-active"` | - * | 11. `$animate` applies the collection of `to` CSS styles to the element which are then handled by the transition | `class="my-animation ng-animate className className-active"` | - * | 12. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate className className-active"` | - * | 13. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` | - * | 14. The returned promise is resolved. | `class="my-animation"` | - * - * @param {DOMElement} element the element that will be the focus of the enter animation - * @param {object} from a collection of CSS styles that will be applied to the element at the start of the animation - * @param {object} to a collection of CSS styles that the element will animate towards - * @param {string=} className an optional CSS class that will be added to the element for the duration of the animation (the default class is `ng-inline-animate`) - * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - animate: function(element, from, to, className, options) { - className = className || 'ng-inline-animate'; - options = parseAnimateOptions(options) || {}; - options.from = to ? from : null; - options.to = to ? to : from; - - return runAnimationPostDigest(function(done) { - return performAnimation('animate', className, stripCommentsFromElement(element), null, null, noop, options, done); - }); - }, - - /** - * @ngdoc method - * @name $animate#enter - * @kind function - * - * @description - * Appends the element to the parentElement element that resides in the document and then runs the enter animation. Once - * the animation is started, the following CSS classes will be present on the element for the duration of the animation: - * - * Below is a breakdown of each step that occurs during enter animation: - * - * | Animation Step | What the element class attribute looks like | - * |-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------| - * | 1. `$animate.enter(...)` is called | `class="my-animation"` | - * | 2. element is inserted into the `parentElement` element or beside the `afterElement` element | `class="my-animation"` | - * | 3. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` | - * | 4. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` | - * | 5. the `.ng-enter` class is added to the element | `class="my-animation ng-animate ng-enter"` | - * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate ng-enter"` | - * | 7. `$animate` blocks all CSS transitions on the element to ensure the `.ng-enter` class styling is applied right away | `class="my-animation ng-animate ng-enter"` | - * | 8. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate ng-enter"` | - * | 9. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate ng-enter"` | - * | 10. the `.ng-enter-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate ng-enter ng-enter-active"` | - * | 11. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate ng-enter ng-enter-active"` | - * | 12. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` | - * | 13. The returned promise is resolved. | `class="my-animation"` | - * - * @param {DOMElement} element the element that will be the focus of the enter animation - * @param {DOMElement} parentElement the parent element of the element that will be the focus of the enter animation - * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the enter animation - * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - enter: function(element, parentElement, afterElement, options) { - options = parseAnimateOptions(options); - element = angular.element(element); - parentElement = prepareElement(parentElement); - afterElement = prepareElement(afterElement); - - classBasedAnimationsBlocked(element, true); - $delegate.enter(element, parentElement, afterElement); - return runAnimationPostDigest(function(done) { - return performAnimation('enter', 'ng-enter', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done); - }); - }, - - /** - * @ngdoc method - * @name $animate#leave - * @kind function - * - * @description - * Runs the leave animation operation and, upon completion, removes the element from the DOM. Once - * the animation is started, the following CSS classes will be added for the duration of the animation: - * - * Below is a breakdown of each step that occurs during leave animation: - * - * | Animation Step | What the element class attribute looks like | - * |-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------| - * | 1. `$animate.leave(...)` is called | `class="my-animation"` | - * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` | - * | 3. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` | - * | 4. the `.ng-leave` class is added to the element | `class="my-animation ng-animate ng-leave"` | - * | 5. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate ng-leave"` | - * | 6. `$animate` blocks all CSS transitions on the element to ensure the `.ng-leave` class styling is applied right away | `class="my-animation ng-animate ng-leave"` | - * | 7. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate ng-leave"` | - * | 8. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate ng-leave"` | - * | 9. the `.ng-leave-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate ng-leave ng-leave-active"` | - * | 10. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate ng-leave ng-leave-active"` | - * | 11. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` | - * | 12. The element is removed from the DOM | ... | - * | 13. The returned promise is resolved. | ... | - * - * @param {DOMElement} element the element that will be the focus of the leave animation - * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - leave: function(element, options) { - options = parseAnimateOptions(options); - element = angular.element(element); - - cancelChildAnimations(element); - classBasedAnimationsBlocked(element, true); - return runAnimationPostDigest(function(done) { - return performAnimation('leave', 'ng-leave', stripCommentsFromElement(element), null, null, function() { - $delegate.leave(element); - }, options, done); - }); - }, - - /** - * @ngdoc method - * @name $animate#move - * @kind function - * - * @description - * Fires the move DOM operation. Just before the animation starts, the animate service will either append it into the parentElement container or - * add the element directly after the afterElement element if present. Then the move animation will be run. Once - * the animation is started, the following CSS classes will be added for the duration of the animation: - * - * Below is a breakdown of each step that occurs during move animation: - * - * | Animation Step | What the element class attribute looks like | - * |----------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------| - * | 1. `$animate.move(...)` is called | `class="my-animation"` | - * | 2. element is moved into the parentElement element or beside the afterElement element | `class="my-animation"` | - * | 3. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` | - * | 4. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` | - * | 5. the `.ng-move` class is added to the element | `class="my-animation ng-animate ng-move"` | - * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate ng-move"` | - * | 7. `$animate` blocks all CSS transitions on the element to ensure the `.ng-move` class styling is applied right away | `class="my-animation ng-animate ng-move"` | - * | 8. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate ng-move"` | - * | 9. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate ng-move"` | - * | 10. the `.ng-move-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate ng-move ng-move-active"` | - * | 11. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate ng-move ng-move-active"` | - * | 12. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` | - * | 13. The returned promise is resolved. | `class="my-animation"` | - * - * @param {DOMElement} element the element that will be the focus of the move animation - * @param {DOMElement} parentElement the parentElement element of the element that will be the focus of the move animation - * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the move animation - * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - move: function(element, parentElement, afterElement, options) { - options = parseAnimateOptions(options); - element = angular.element(element); - parentElement = prepareElement(parentElement); - afterElement = prepareElement(afterElement); - - cancelChildAnimations(element); - classBasedAnimationsBlocked(element, true); - $delegate.move(element, parentElement, afterElement); - return runAnimationPostDigest(function(done) { - return performAnimation('move', 'ng-move', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done); - }); - }, - - /** - * @ngdoc method - * @name $animate#addClass - * - * @description - * Triggers a custom animation event based off the className variable and then attaches the className value to the element as a CSS class. - * Unlike the other animation methods, the animate service will suffix the className value with {@type -add} in order to provide - * the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if no CSS transitions - * or keyframes are defined on the -add-active or base CSS class). - * - * Below is a breakdown of each step that occurs during addClass animation: - * - * | Animation Step | What the element class attribute looks like | - * |--------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------| - * | 1. `$animate.addClass(element, 'super')` is called | `class="my-animation"` | - * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` | - * | 3. the `.super-add` class is added to the element | `class="my-animation ng-animate super-add"` | - * | 4. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate super-add"` | - * | 5. the `.super` and `.super-add-active` classes are added (this triggers the CSS transition/animation) | `class="my-animation ng-animate super super-add super-add-active"` | - * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate super super-add super-add-active"` | - * | 7. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate super super-add super-add-active"` | - * | 8. The animation ends and all generated CSS classes are removed from the element | `class="my-animation super"` | - * | 9. The super class is kept on the element | `class="my-animation super"` | - * | 10. The returned promise is resolved. | `class="my-animation super"` | - * - * @param {DOMElement} element the element that will be animated - * @param {string} className the CSS class that will be added to the element and then animated - * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - addClass: function(element, className, options) { - return this.setClass(element, className, [], options); - }, - - /** - * @ngdoc method - * @name $animate#removeClass - * - * @description - * Triggers a custom animation event based off the className variable and then removes the CSS class provided by the className value - * from the element. Unlike the other animation methods, the animate service will suffix the className value with {@type -remove} in - * order to provide the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if - * no CSS transitions or keyframes are defined on the -remove or base CSS classes). - * - * Below is a breakdown of each step that occurs during removeClass animation: - * - * | Animation Step | What the element class attribute looks like | - * |----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------| - * | 1. `$animate.removeClass(element, 'super')` is called | `class="my-animation super"` | - * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation super ng-animate"` | - * | 3. the `.super-remove` class is added to the element | `class="my-animation super ng-animate super-remove"` | - * | 4. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation super ng-animate super-remove"` | - * | 5. the `.super-remove-active` classes are added and `.super` is removed (this triggers the CSS transition/animation) | `class="my-animation ng-animate super-remove super-remove-active"` | - * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate super-remove super-remove-active"` | - * | 7. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate super-remove super-remove-active"` | - * | 8. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` | - * | 9. The returned promise is resolved. | `class="my-animation"` | - * - * - * @param {DOMElement} element the element that will be animated - * @param {string} className the CSS class that will be animated and then removed from the element - * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - removeClass: function(element, className, options) { - return this.setClass(element, [], className, options); - }, - - /** - * - * @ngdoc method - * @name $animate#setClass - * - * @description Adds and/or removes the given CSS classes to and from the element. - * Once complete, the `done()` callback will be fired (if provided). - * - * | Animation Step | What the element class attribute looks like | - * |----------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------| - * | 1. `$animate.setClass(element, 'on', 'off')` is called | `class="my-animation off"` | - * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate off"` | - * | 3. the `.on-add` and `.off-remove` classes are added to the element | `class="my-animation ng-animate on-add off-remove off"` | - * | 4. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate on-add off-remove off"` | - * | 5. the `.on`, `.on-add-active` and `.off-remove-active` classes are added and `.off` is removed (this triggers the CSS transition/animation) | `class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active"` | - * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active"` | - * | 7. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active"` | - * | 8. The animation ends and all generated CSS classes are removed from the element | `class="my-animation on"` | - * | 9. The returned promise is resolved. | `class="my-animation on"` | - * - * @param {DOMElement} element the element which will have its CSS classes changed - * removed from it - * @param {string} add the CSS classes which will be added to the element - * @param {string} remove the CSS class which will be removed from the element - * CSS classes have been set on the element - * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - setClass: function(element, add, remove, options) { - options = parseAnimateOptions(options); - - var STORAGE_KEY = '$$animateClasses'; - element = angular.element(element); - element = stripCommentsFromElement(element); - - if (classBasedAnimationsBlocked(element)) { - return $delegate.$$setClassImmediately(element, add, remove, options); - } - - // we're using a combined array for both the add and remove - // operations since the ORDER OF addClass and removeClass matters - var classes, cache = element.data(STORAGE_KEY); - var hasCache = !!cache; - if (!cache) { - cache = {}; - cache.classes = {}; - } - classes = cache.classes; - - add = isArray(add) ? add : add.split(' '); - forEach(add, function(c) { - if (c && c.length) { - classes[c] = true; - } - }); - - remove = isArray(remove) ? remove : remove.split(' '); - forEach(remove, function(c) { - if (c && c.length) { - classes[c] = false; - } - }); - - if (hasCache) { - if (options && cache.options) { - cache.options = angular.extend(cache.options || {}, options); - } - - //the digest cycle will combine all the animations into one function - return cache.promise; - } else { - element.data(STORAGE_KEY, cache = { - classes: classes, - options: options - }); - } - - return cache.promise = runAnimationPostDigest(function(done) { - var parentElement = element.parent(); - var elementNode = extractElementNode(element); - var parentNode = elementNode.parentNode; - // TODO(matsko): move this code into the animationsDisabled() function once #8092 is fixed - if (!parentNode || parentNode['$$NG_REMOVED'] || elementNode['$$NG_REMOVED']) { - done(); - return; - } - - var cache = element.data(STORAGE_KEY); - element.removeData(STORAGE_KEY); - - var state = element.data(NG_ANIMATE_STATE) || {}; - var classes = resolveElementClasses(element, cache, state.active); - return !classes - ? done() - : performAnimation('setClass', classes, element, parentElement, null, function() { - if (classes[0]) $delegate.$$addClassImmediately(element, classes[0]); - if (classes[1]) $delegate.$$removeClassImmediately(element, classes[1]); - }, cache.options, done); - }); - }, - - /** - * @ngdoc method - * @name $animate#cancel - * @kind function - * - * @param {Promise} animationPromise The animation promise that is returned when an animation is started. - * - * @description - * Cancels the provided animation. - */ - cancel: function(promise) { - promise.$$cancelFn(); - }, - - /** - * @ngdoc method - * @name $animate#enabled - * @kind function - * - * @param {boolean=} value If provided then set the animation on or off. - * @param {DOMElement=} element If provided then the element will be used to represent the enable/disable operation - * @return {boolean} Current animation state. - * - * @description - * Globally enables/disables animations. - * - */ - enabled: function(value, element) { - switch (arguments.length) { - case 2: - if (value) { - cleanup(element); - } else { - var data = element.data(NG_ANIMATE_STATE) || {}; - data.disabled = true; - element.data(NG_ANIMATE_STATE, data); - } - break; - - case 1: - rootAnimateState.disabled = !value; - break; - - default: - value = !rootAnimateState.disabled; - break; - } - return !!value; - } - }; - - /* - all animations call this shared animation triggering function internally. - The animationEvent variable refers to the JavaScript animation event that will be triggered - and the className value is the name of the animation that will be applied within the - CSS code. Element, `parentElement` and `afterElement` are provided DOM elements for the animation - and the onComplete callback will be fired once the animation is fully complete. - */ - function performAnimation(animationEvent, className, element, parentElement, afterElement, domOperation, options, doneCallback) { - var noopCancel = noop; - var runner = animationRunner(element, animationEvent, className, options); - if (!runner) { - fireDOMOperation(); - fireBeforeCallbackAsync(); - fireAfterCallbackAsync(); - closeAnimation(); - return noopCancel; - } - - animationEvent = runner.event; - className = runner.className; - var elementEvents = angular.element._data(runner.node); - elementEvents = elementEvents && elementEvents.events; - - if (!parentElement) { - parentElement = afterElement ? afterElement.parent() : element.parent(); - } - - //skip the animation if animations are disabled, a parent is already being animated, - //the element is not currently attached to the document body or then completely close - //the animation if any matching animations are not found at all. - //NOTE: IE8 + IE9 should close properly (run closeAnimation()) in case an animation was found. - if (animationsDisabled(element, parentElement)) { - fireDOMOperation(); - fireBeforeCallbackAsync(); - fireAfterCallbackAsync(); - closeAnimation(); - return noopCancel; - } - - var ngAnimateState = element.data(NG_ANIMATE_STATE) || {}; - var runningAnimations = ngAnimateState.active || {}; - var totalActiveAnimations = ngAnimateState.totalActive || 0; - var lastAnimation = ngAnimateState.last; - var skipAnimation = false; - - if (totalActiveAnimations > 0) { - var animationsToCancel = []; - if (!runner.isClassBased) { - if (animationEvent == 'leave' && runningAnimations['ng-leave']) { - skipAnimation = true; - } else { - //cancel all animations when a structural animation takes place - for (var klass in runningAnimations) { - animationsToCancel.push(runningAnimations[klass]); - } - ngAnimateState = {}; - cleanup(element, true); - } - } else if (lastAnimation.event == 'setClass') { - animationsToCancel.push(lastAnimation); - cleanup(element, className); - } else if (runningAnimations[className]) { - var current = runningAnimations[className]; - if (current.event == animationEvent) { - skipAnimation = true; - } else { - animationsToCancel.push(current); - cleanup(element, className); - } - } - - if (animationsToCancel.length > 0) { - forEach(animationsToCancel, function(operation) { - operation.cancel(); - }); - } - } - - if (runner.isClassBased - && !runner.isSetClassOperation - && animationEvent != 'animate' - && !skipAnimation) { - skipAnimation = (animationEvent == 'addClass') == element.hasClass(className); //opposite of XOR - } - - if (skipAnimation) { - fireDOMOperation(); - fireBeforeCallbackAsync(); - fireAfterCallbackAsync(); - fireDoneCallbackAsync(); - return noopCancel; - } - - runningAnimations = ngAnimateState.active || {}; - totalActiveAnimations = ngAnimateState.totalActive || 0; - - if (animationEvent == 'leave') { - //there's no need to ever remove the listener since the element - //will be removed (destroyed) after the leave animation ends or - //is cancelled midway - element.one('$destroy', function(e) { - var element = angular.element(this); - var state = element.data(NG_ANIMATE_STATE); - if (state) { - var activeLeaveAnimation = state.active['ng-leave']; - if (activeLeaveAnimation) { - activeLeaveAnimation.cancel(); - cleanup(element, 'ng-leave'); - } - } - }); - } - - //the ng-animate class does nothing, but it's here to allow for - //parent animations to find and cancel child animations when needed - $$jqLite.addClass(element, NG_ANIMATE_CLASS_NAME); - if (options && options.tempClasses) { - forEach(options.tempClasses, function(className) { - $$jqLite.addClass(element, className); - }); - } - - var localAnimationCount = globalAnimationCounter++; - totalActiveAnimations++; - runningAnimations[className] = runner; - - element.data(NG_ANIMATE_STATE, { - last: runner, - active: runningAnimations, - index: localAnimationCount, - totalActive: totalActiveAnimations - }); - - //first we run the before animations and when all of those are complete - //then we perform the DOM operation and run the next set of animations - fireBeforeCallbackAsync(); - runner.before(function(cancelled) { - var data = element.data(NG_ANIMATE_STATE); - cancelled = cancelled || - !data || !data.active[className] || - (runner.isClassBased && data.active[className].event != animationEvent); - - fireDOMOperation(); - if (cancelled === true) { - closeAnimation(); - } else { - fireAfterCallbackAsync(); - runner.after(closeAnimation); - } - }); - - return runner.cancel; - - function fireDOMCallback(animationPhase) { - var eventName = '$animate:' + animationPhase; - if (elementEvents && elementEvents[eventName] && elementEvents[eventName].length > 0) { - $$asyncCallback(function() { - element.triggerHandler(eventName, { - event: animationEvent, - className: className - }); - }); - } - } - - function fireBeforeCallbackAsync() { - fireDOMCallback('before'); - } - - function fireAfterCallbackAsync() { - fireDOMCallback('after'); - } - - function fireDoneCallbackAsync() { - fireDOMCallback('close'); - doneCallback(); - } - - //it is less complicated to use a flag than managing and canceling - //timeouts containing multiple callbacks. - function fireDOMOperation() { - if (!fireDOMOperation.hasBeenRun) { - fireDOMOperation.hasBeenRun = true; - domOperation(); - } - } - - function closeAnimation() { - if (!closeAnimation.hasBeenRun) { - if (runner) { //the runner doesn't exist if it fails to instantiate - runner.applyStyles(); - } - - closeAnimation.hasBeenRun = true; - if (options && options.tempClasses) { - forEach(options.tempClasses, function(className) { - $$jqLite.removeClass(element, className); - }); - } - - var data = element.data(NG_ANIMATE_STATE); - if (data) { - - /* only structural animations wait for reflow before removing an - animation, but class-based animations don't. An example of this - failing would be when a parent HTML tag has a ng-class attribute - causing ALL directives below to skip animations during the digest */ - if (runner && runner.isClassBased) { - cleanup(element, className); - } else { - $$asyncCallback(function() { - var data = element.data(NG_ANIMATE_STATE) || {}; - if (localAnimationCount == data.index) { - cleanup(element, className, animationEvent); - } - }); - element.data(NG_ANIMATE_STATE, data); - } - } - fireDoneCallbackAsync(); - } - } - } - - function cancelChildAnimations(element) { - var node = extractElementNode(element); - if (node) { - var nodes = angular.isFunction(node.getElementsByClassName) ? - node.getElementsByClassName(NG_ANIMATE_CLASS_NAME) : - node.querySelectorAll('.' + NG_ANIMATE_CLASS_NAME); - forEach(nodes, function(element) { - element = angular.element(element); - var data = element.data(NG_ANIMATE_STATE); - if (data && data.active) { - forEach(data.active, function(runner) { - runner.cancel(); - }); - } - }); - } - } - - function cleanup(element, className) { - if (isMatchingElement(element, $rootElement)) { - if (!rootAnimateState.disabled) { - rootAnimateState.running = false; - rootAnimateState.structural = false; - } - } else if (className) { - var data = element.data(NG_ANIMATE_STATE) || {}; - - var removeAnimations = className === true; - if (!removeAnimations && data.active && data.active[className]) { - data.totalActive--; - delete data.active[className]; - } - - if (removeAnimations || !data.totalActive) { - $$jqLite.removeClass(element, NG_ANIMATE_CLASS_NAME); - element.removeData(NG_ANIMATE_STATE); - } - } - } - - function animationsDisabled(element, parentElement) { - if (rootAnimateState.disabled) { - return true; - } - - if (isMatchingElement(element, $rootElement)) { - return rootAnimateState.running; - } - - var allowChildAnimations, parentRunningAnimation, hasParent; - do { - //the element did not reach the root element which means that it - //is not apart of the DOM. Therefore there is no reason to do - //any animations on it - if (parentElement.length === 0) break; - - var isRoot = isMatchingElement(parentElement, $rootElement); - var state = isRoot ? rootAnimateState : (parentElement.data(NG_ANIMATE_STATE) || {}); - if (state.disabled) { - return true; - } - - //no matter what, for an animation to work it must reach the root element - //this implies that the element is attached to the DOM when the animation is run - if (isRoot) { - hasParent = true; - } - - //once a flag is found that is strictly false then everything before - //it will be discarded and all child animations will be restricted - if (allowChildAnimations !== false) { - var animateChildrenFlag = parentElement.data(NG_ANIMATE_CHILDREN); - if (angular.isDefined(animateChildrenFlag)) { - allowChildAnimations = animateChildrenFlag; - } - } - - parentRunningAnimation = parentRunningAnimation || - state.running || - (state.last && !state.last.isClassBased); - } - while (parentElement = parentElement.parent()); - - return !hasParent || (!allowChildAnimations && parentRunningAnimation); - } - }]); - - $animateProvider.register('', ['$window', '$sniffer', '$timeout', '$$animateReflow', - function($window, $sniffer, $timeout, $$animateReflow) { - // Detect proper transitionend/animationend event names. - var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT; - - // If unprefixed events are not supported but webkit-prefixed are, use the latter. - // Otherwise, just use W3C names, browsers not supporting them at all will just ignore them. - // Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend` - // but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`. - // Register both events in case `window.onanimationend` is not supported because of that, - // do the same for `transitionend` as Safari is likely to exhibit similar behavior. - // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit - // therefore there is no reason to test anymore for other vendor prefixes: http://caniuse.com/#search=transition - if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) { - CSS_PREFIX = '-webkit-'; - TRANSITION_PROP = 'WebkitTransition'; - TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend'; - } else { - TRANSITION_PROP = 'transition'; - TRANSITIONEND_EVENT = 'transitionend'; - } - - if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) { - CSS_PREFIX = '-webkit-'; - ANIMATION_PROP = 'WebkitAnimation'; - ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend'; - } else { - ANIMATION_PROP = 'animation'; - ANIMATIONEND_EVENT = 'animationend'; - } - - var DURATION_KEY = 'Duration'; - var PROPERTY_KEY = 'Property'; - var DELAY_KEY = 'Delay'; - var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount'; - var ANIMATION_PLAYSTATE_KEY = 'PlayState'; - var NG_ANIMATE_PARENT_KEY = '$$ngAnimateKey'; - var NG_ANIMATE_CSS_DATA_KEY = '$$ngAnimateCSS3Data'; - var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3; - var CLOSING_TIME_BUFFER = 1.5; - var ONE_SECOND = 1000; - - var lookupCache = {}; - var parentCounter = 0; - var animationReflowQueue = []; - var cancelAnimationReflow; - function clearCacheAfterReflow() { - if (!cancelAnimationReflow) { - cancelAnimationReflow = $$animateReflow(function() { - animationReflowQueue = []; - cancelAnimationReflow = null; - lookupCache = {}; - }); - } - } - - function afterReflow(element, callback) { - if (cancelAnimationReflow) { - cancelAnimationReflow(); - } - animationReflowQueue.push(callback); - cancelAnimationReflow = $$animateReflow(function() { - forEach(animationReflowQueue, function(fn) { - fn(); - }); - - animationReflowQueue = []; - cancelAnimationReflow = null; - lookupCache = {}; - }); - } - - var closingTimer = null; - var closingTimestamp = 0; - var animationElementQueue = []; - function animationCloseHandler(element, totalTime) { - var node = extractElementNode(element); - element = angular.element(node); - - //this item will be garbage collected by the closing - //animation timeout - animationElementQueue.push(element); - - //but it may not need to cancel out the existing timeout - //if the timestamp is less than the previous one - var futureTimestamp = Date.now() + totalTime; - if (futureTimestamp <= closingTimestamp) { - return; - } - - $timeout.cancel(closingTimer); - - closingTimestamp = futureTimestamp; - closingTimer = $timeout(function() { - closeAllAnimations(animationElementQueue); - animationElementQueue = []; - }, totalTime, false); - } - - function closeAllAnimations(elements) { - forEach(elements, function(element) { - var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY); - if (elementData) { - forEach(elementData.closeAnimationFns, function(fn) { - fn(); - }); - } - }); - } - - function getElementAnimationDetails(element, cacheKey) { - var data = cacheKey ? lookupCache[cacheKey] : null; - if (!data) { - var transitionDuration = 0; - var transitionDelay = 0; - var animationDuration = 0; - var animationDelay = 0; - - //we want all the styles defined before and after - forEach(element, function(element) { - if (element.nodeType == ELEMENT_NODE) { - var elementStyles = $window.getComputedStyle(element) || {}; - - var transitionDurationStyle = elementStyles[TRANSITION_PROP + DURATION_KEY]; - transitionDuration = Math.max(parseMaxTime(transitionDurationStyle), transitionDuration); - - var transitionDelayStyle = elementStyles[TRANSITION_PROP + DELAY_KEY]; - transitionDelay = Math.max(parseMaxTime(transitionDelayStyle), transitionDelay); - - var animationDelayStyle = elementStyles[ANIMATION_PROP + DELAY_KEY]; - animationDelay = Math.max(parseMaxTime(elementStyles[ANIMATION_PROP + DELAY_KEY]), animationDelay); - - var aDuration = parseMaxTime(elementStyles[ANIMATION_PROP + DURATION_KEY]); - - if (aDuration > 0) { - aDuration *= parseInt(elementStyles[ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY], 10) || 1; - } - animationDuration = Math.max(aDuration, animationDuration); - } - }); - data = { - total: 0, - transitionDelay: transitionDelay, - transitionDuration: transitionDuration, - animationDelay: animationDelay, - animationDuration: animationDuration - }; - if (cacheKey) { - lookupCache[cacheKey] = data; - } - } - return data; - } - - function parseMaxTime(str) { - var maxValue = 0; - var values = isString(str) ? - str.split(/\s*,\s*/) : - []; - forEach(values, function(value) { - maxValue = Math.max(parseFloat(value) || 0, maxValue); - }); - return maxValue; - } - - function getCacheKey(element) { - var parentElement = element.parent(); - var parentID = parentElement.data(NG_ANIMATE_PARENT_KEY); - if (!parentID) { - parentElement.data(NG_ANIMATE_PARENT_KEY, ++parentCounter); - parentID = parentCounter; - } - return parentID + '-' + extractElementNode(element).getAttribute('class'); - } - - function animateSetup(animationEvent, element, className, styles) { - var structural = ['ng-enter','ng-leave','ng-move'].indexOf(className) >= 0; - - var cacheKey = getCacheKey(element); - var eventCacheKey = cacheKey + ' ' + className; - var itemIndex = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0; - - var stagger = {}; - if (itemIndex > 0) { - var staggerClassName = className + '-stagger'; - var staggerCacheKey = cacheKey + ' ' + staggerClassName; - var applyClasses = !lookupCache[staggerCacheKey]; - - applyClasses && $$jqLite.addClass(element, staggerClassName); - - stagger = getElementAnimationDetails(element, staggerCacheKey); - - applyClasses && $$jqLite.removeClass(element, staggerClassName); - } - - $$jqLite.addClass(element, className); - - var formerData = element.data(NG_ANIMATE_CSS_DATA_KEY) || {}; - var timings = getElementAnimationDetails(element, eventCacheKey); - var transitionDuration = timings.transitionDuration; - var animationDuration = timings.animationDuration; - - if (structural && transitionDuration === 0 && animationDuration === 0) { - $$jqLite.removeClass(element, className); - return false; - } - - var blockTransition = styles || (structural && transitionDuration > 0); - var blockAnimation = animationDuration > 0 && - stagger.animationDelay > 0 && - stagger.animationDuration === 0; - - var closeAnimationFns = formerData.closeAnimationFns || []; - element.data(NG_ANIMATE_CSS_DATA_KEY, { - stagger: stagger, - cacheKey: eventCacheKey, - running: formerData.running || 0, - itemIndex: itemIndex, - blockTransition: blockTransition, - closeAnimationFns: closeAnimationFns - }); - - var node = extractElementNode(element); - - if (blockTransition) { - blockTransitions(node, true); - if (styles) { - element.css(styles); - } - } - - if (blockAnimation) { - blockAnimations(node, true); - } - - return true; - } - - function animateRun(animationEvent, element, className, activeAnimationComplete, styles) { - var node = extractElementNode(element); - var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY); - if (node.getAttribute('class').indexOf(className) == -1 || !elementData) { - activeAnimationComplete(); - return; - } - - var activeClassName = ''; - var pendingClassName = ''; - forEach(className.split(' '), function(klass, i) { - var prefix = (i > 0 ? ' ' : '') + klass; - activeClassName += prefix + '-active'; - pendingClassName += prefix + '-pending'; - }); - - var style = ''; - var appliedStyles = []; - var itemIndex = elementData.itemIndex; - var stagger = elementData.stagger; - var staggerTime = 0; - if (itemIndex > 0) { - var transitionStaggerDelay = 0; - if (stagger.transitionDelay > 0 && stagger.transitionDuration === 0) { - transitionStaggerDelay = stagger.transitionDelay * itemIndex; - } - - var animationStaggerDelay = 0; - if (stagger.animationDelay > 0 && stagger.animationDuration === 0) { - animationStaggerDelay = stagger.animationDelay * itemIndex; - appliedStyles.push(CSS_PREFIX + 'animation-play-state'); - } - - staggerTime = Math.round(Math.max(transitionStaggerDelay, animationStaggerDelay) * 100) / 100; - } - - if (!staggerTime) { - $$jqLite.addClass(element, activeClassName); - if (elementData.blockTransition) { - blockTransitions(node, false); - } - } - - var eventCacheKey = elementData.cacheKey + ' ' + activeClassName; - var timings = getElementAnimationDetails(element, eventCacheKey); - var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration); - if (maxDuration === 0) { - $$jqLite.removeClass(element, activeClassName); - animateClose(element, className); - activeAnimationComplete(); - return; - } - - if (!staggerTime && styles && Object.keys(styles).length > 0) { - if (!timings.transitionDuration) { - element.css('transition', timings.animationDuration + 's linear all'); - appliedStyles.push('transition'); - } - element.css(styles); - } - - var maxDelay = Math.max(timings.transitionDelay, timings.animationDelay); - var maxDelayTime = maxDelay * ONE_SECOND; - - if (appliedStyles.length > 0) { - //the element being animated may sometimes contain comment nodes in - //the jqLite object, so we're safe to use a single variable to house - //the styles since there is always only one element being animated - var oldStyle = node.getAttribute('style') || ''; - if (oldStyle.charAt(oldStyle.length - 1) !== ';') { - oldStyle += ';'; - } - node.setAttribute('style', oldStyle + ' ' + style); - } - - var startTime = Date.now(); - var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT; - var animationTime = (maxDelay + maxDuration) * CLOSING_TIME_BUFFER; - var totalTime = (staggerTime + animationTime) * ONE_SECOND; - - var staggerTimeout; - if (staggerTime > 0) { - $$jqLite.addClass(element, pendingClassName); - staggerTimeout = $timeout(function() { - staggerTimeout = null; - - if (timings.transitionDuration > 0) { - blockTransitions(node, false); - } - if (timings.animationDuration > 0) { - blockAnimations(node, false); - } - - $$jqLite.addClass(element, activeClassName); - $$jqLite.removeClass(element, pendingClassName); - - if (styles) { - if (timings.transitionDuration === 0) { - element.css('transition', timings.animationDuration + 's linear all'); - } - element.css(styles); - appliedStyles.push('transition'); - } - }, staggerTime * ONE_SECOND, false); - } - - element.on(css3AnimationEvents, onAnimationProgress); - elementData.closeAnimationFns.push(function() { - onEnd(); - activeAnimationComplete(); - }); - - elementData.running++; - animationCloseHandler(element, totalTime); - return onEnd; - - // This will automatically be called by $animate so - // there is no need to attach this internally to the - // timeout done method. - function onEnd() { - element.off(css3AnimationEvents, onAnimationProgress); - $$jqLite.removeClass(element, activeClassName); - $$jqLite.removeClass(element, pendingClassName); - if (staggerTimeout) { - $timeout.cancel(staggerTimeout); - } - animateClose(element, className); - var node = extractElementNode(element); - for (var i in appliedStyles) { - node.style.removeProperty(appliedStyles[i]); - } - } - - function onAnimationProgress(event) { - event.stopPropagation(); - var ev = event.originalEvent || event; - var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now(); - - /* Firefox (or possibly just Gecko) likes to not round values up - * when a ms measurement is used for the animation */ - var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES)); - - /* $manualTimeStamp is a mocked timeStamp value which is set - * within browserTrigger(). This is only here so that tests can - * mock animations properly. Real events fallback to event.timeStamp, - * or, if they don't, then a timeStamp is automatically created for them. - * We're checking to see if the timeStamp surpasses the expected delay, - * but we're using elapsedTime instead of the timeStamp on the 2nd - * pre-condition since animations sometimes close off early */ - if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) { - activeAnimationComplete(); - } - } - } - - function blockTransitions(node, bool) { - node.style[TRANSITION_PROP + PROPERTY_KEY] = bool ? 'none' : ''; - } - - function blockAnimations(node, bool) { - node.style[ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY] = bool ? 'paused' : ''; - } - - function animateBefore(animationEvent, element, className, styles) { - if (animateSetup(animationEvent, element, className, styles)) { - return function(cancelled) { - cancelled && animateClose(element, className); - }; - } - } - - function animateAfter(animationEvent, element, className, afterAnimationComplete, styles) { - if (element.data(NG_ANIMATE_CSS_DATA_KEY)) { - return animateRun(animationEvent, element, className, afterAnimationComplete, styles); - } else { - animateClose(element, className); - afterAnimationComplete(); - } - } - - function animate(animationEvent, element, className, animationComplete, options) { - //If the animateSetup function doesn't bother returning a - //cancellation function then it means that there is no animation - //to perform at all - var preReflowCancellation = animateBefore(animationEvent, element, className, options.from); - if (!preReflowCancellation) { - clearCacheAfterReflow(); - animationComplete(); - return; - } - - //There are two cancellation functions: one is before the first - //reflow animation and the second is during the active state - //animation. The first function will take care of removing the - //data from the element which will not make the 2nd animation - //happen in the first place - var cancel = preReflowCancellation; - afterReflow(element, function() { - //once the reflow is complete then we point cancel to - //the new cancellation function which will remove all of the - //animation properties from the active animation - cancel = animateAfter(animationEvent, element, className, animationComplete, options.to); - }); - - return function(cancelled) { - (cancel || noop)(cancelled); - }; - } - - function animateClose(element, className) { - $$jqLite.removeClass(element, className); - var data = element.data(NG_ANIMATE_CSS_DATA_KEY); - if (data) { - if (data.running) { - data.running--; - } - if (!data.running || data.running === 0) { - element.removeData(NG_ANIMATE_CSS_DATA_KEY); - } - } - } - - return { - animate: function(element, className, from, to, animationCompleted, options) { - options = options || {}; - options.from = from; - options.to = to; - return animate('animate', element, className, animationCompleted, options); - }, - - enter: function(element, animationCompleted, options) { - options = options || {}; - return animate('enter', element, 'ng-enter', animationCompleted, options); - }, - - leave: function(element, animationCompleted, options) { - options = options || {}; - return animate('leave', element, 'ng-leave', animationCompleted, options); - }, - - move: function(element, animationCompleted, options) { - options = options || {}; - return animate('move', element, 'ng-move', animationCompleted, options); - }, - - beforeSetClass: function(element, add, remove, animationCompleted, options) { - options = options || {}; - var className = suffixClasses(remove, '-remove') + ' ' + - suffixClasses(add, '-add'); - var cancellationMethod = animateBefore('setClass', element, className, options.from); - if (cancellationMethod) { - afterReflow(element, animationCompleted); - return cancellationMethod; - } - clearCacheAfterReflow(); - animationCompleted(); - }, - - beforeAddClass: function(element, className, animationCompleted, options) { - options = options || {}; - var cancellationMethod = animateBefore('addClass', element, suffixClasses(className, '-add'), options.from); - if (cancellationMethod) { - afterReflow(element, animationCompleted); - return cancellationMethod; - } - clearCacheAfterReflow(); - animationCompleted(); - }, - - beforeRemoveClass: function(element, className, animationCompleted, options) { - options = options || {}; - var cancellationMethod = animateBefore('removeClass', element, suffixClasses(className, '-remove'), options.from); - if (cancellationMethod) { - afterReflow(element, animationCompleted); - return cancellationMethod; - } - clearCacheAfterReflow(); - animationCompleted(); - }, - - setClass: function(element, add, remove, animationCompleted, options) { - options = options || {}; - remove = suffixClasses(remove, '-remove'); - add = suffixClasses(add, '-add'); - var className = remove + ' ' + add; - return animateAfter('setClass', element, className, animationCompleted, options.to); - }, - - addClass: function(element, className, animationCompleted, options) { - options = options || {}; - return animateAfter('addClass', element, suffixClasses(className, '-add'), animationCompleted, options.to); - }, - - removeClass: function(element, className, animationCompleted, options) { - options = options || {}; - return animateAfter('removeClass', element, suffixClasses(className, '-remove'), animationCompleted, options.to); - } - }; - - function suffixClasses(classes, suffix) { - var className = ''; - classes = isArray(classes) ? classes : classes.split(/\s+/); - forEach(classes, function(klass, i) { - if (klass && klass.length > 0) { - className += (i > 0 ? ' ' : '') + klass + suffix; - } - }); - return className; - } - }]); - }]); diff --git a/src/ngAnimate/animateChildrenDirective.js b/src/ngAnimate/animateChildrenDirective.js new file mode 100644 index 000000000000..3962a632d890 --- /dev/null +++ b/src/ngAnimate/animateChildrenDirective.js @@ -0,0 +1,15 @@ +'use strict'; + +var $$AnimateChildrenDirective = [function() { + return function(scope, element, attrs) { + var val = attrs.ngAnimateChildren; + if (angular.isString(val) && val.length === 0) { //empty attribute + element.data(NG_ANIMATE_CHILDREN_DATA, true); + } else { + attrs.$observe('ngAnimateChildren', function(value) { + value = value === 'on' || value === 'true'; + element.data(NG_ANIMATE_CHILDREN_DATA, value); + }); + } + }; +}]; diff --git a/src/ngAnimate/animateCss.js b/src/ngAnimate/animateCss.js new file mode 100644 index 000000000000..1280da9b714b --- /dev/null +++ b/src/ngAnimate/animateCss.js @@ -0,0 +1,997 @@ +'use strict'; + +/** + * @ngdoc service + * @name $animateCss + * @kind object + * + * @description + * The `$animateCss` service is a useful utility to trigger customized CSS-based transitions/keyframes + * from a JavaScript-based animation or directly from a directive. The purpose of `$animateCss` is NOT + * to side-step how `$animate` and ngAnimate work, but the goal is to allow pre-existing animations or + * directives to create more complex animations that can be purely driven using CSS code. + * + * Note that only browsers that support CSS transitions and/or keyframe animations are capable of + * rendering animations triggered via `$animateCss` (bad news for IE9 and lower). + * + * ## Usage + * Once again, `$animateCss` is designed to be used inside of a registered JavaScript animation that + * is powered by ngAnimate. It is possible to use `$animateCss` directly inside of a directive, however, + * any automatic control over cancelling animations and/or preventing animations from being run on + * child elements will not be handled by Angular. For this to work as expected, please use `$animate` to + * trigger the animation and then setup a JavaScript animation that injects `$animateCss` to trigger + * the CSS animation. + * + * The example below shows how we can create a folding animation on an element using `ng-if`: + * + * ```html + * + *
+ * This element will go BOOM + *
+ * + * ``` + * + * Now we create the **JavaScript animation** that will trigger the CSS transition: + * + * ```js + * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var height = element[0].offsetHeight; + * var animation = $animateCss(element, { + * from: { height:'0px' }, + * to: { height:height + 'px' }, + * duration: 1 // one second + * }); + * + * // if no possible animation can be triggered due + * // to the combination of options then `animation` + * // will be returned as undefined + * animation.start().done(doneFn); + * } + * } + * }]); + * ``` + * + * ## More Advanced Uses + * + * `$animateCss` is the underlying code that ngAnimate uses to power **CSS-based animations** behind the scenes. Therefore CSS hooks + * like `.ng-EVENT`, `.ng-EVENT-active`, `.ng-EVENT-stagger` are all features that can be triggered using `$animateCss` via JavaScript code. + * + * This also means that just about any combination of adding classes, removing classes, setting styles, dynamically setting a keyframe animation, + * applying a hardcoded duration or delay value, changing the animation easing or applying a stagger animation are all options that work with + * `$animateCss`. The service itself is smart enough to figure out the combination of options and examine the element styling properties in order + * to provide a working animation that will run in CSS. + * + * The example below showcases a more advanced version of the `.fold-animation` from the example above: + * + * ```js + * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var height = element[0].offsetHeight; + * var animation = $animateCss(element, { + * addClass: 'red large-text pulse-twice', + * easing: 'ease-out', + * from: { height:'0px' }, + * to: { height:height + 'px' }, + * duration: 1 // one second + * }); + * + * // if no possible animation can be triggered due + * // to the combination of options then `animation` + * // will be returned as undefined + * animation.start().done(doneFn); + * } + * } + * }]); + * ``` + * + * Since we're adding/removing CSS classes then the CSS transition will also pick those up: + * + * ```css + * /* since a hardcoded duration value of 1 was provided in the JavaScript animation code, + * the CSS classes below will be transitioned despite them being defined as regular CSS classes */ + * .red { background:red; } + * .large-text { font-size:20px; } + * + * /* we can also use a keyframe animation and $animateCss will make it work alongside the transition */ + * .pulse-twice { + * animation: 0.5s pulse linear 2; + * -webkit-animation: 0.5s pulse linear 2; + * } + * + * @keyframes pulse { + * from { transform: scale(0.5); } + * to { transform: scale(1.5); } + * } + * + * @-webkit-keyframes pulse { + * from { -webkit-transform: scale(0.5); } + * to { -webkit-transform: scale(1.5); } + * } + * ``` + * + * Given this complex combination of CSS classes, styles and options, `$animateCss` will figure everything out and make the animation happen. + * + * ## How the Options are handled + * + * `$animateCss` is very versatile and intelligent when it comes to figuring out what configurations to apply to the element to ensure the animation + * works with the options provided. Say for example we were adding a class that contained a keyframe value and we wanted to also animate some inline + * styles using the `from` and `to` properties. + * + * ```js + * var animation = $animateCss(element, { + * from: { background:'red' }, + * to: { background:'blue' } + * }); + * ``` + * + * ```css + * .rotating-animation { + * animation:0.5s rotate linear; + * -webkit-animation:0.5s rotate linear; + * } + * + * @keyframes rotate { + * from { transform: rotate(0deg); } + * to { transform: rotate(360deg); } + * } + * + * @-webkit-keyframes rotate { + * from { -webkit-transform: rotate(0deg); } + * to { -webkit-transform: rotate(360deg); } + * } + * ``` + * + * The missing pieces here are that we do not have a transition set (within the CSS code nor within the `$animateCss` options) and the duration of the animation is + * going to be detected from what the keyframe styles on the CSS class are. In this event, `$animateCss` will automatically create an inline transition + * style matching the duration detected from the keyframe style (which is present in the CSS class that is being added) and then prepare both the transition + * and keyframe animations to run in parallel on the element. Then when the animation is underway the provided `from` and `to` CSS styles will be applied + * and spread across the transition and keyframe animation. + * + * ## What is returned + * + * `$animateCss` works in two stages: a preparation phase and an animation phase. Therefore when `$animateCss` is first called it will NOT actually + * start the animation. All that is going on here is that the element is being prepared for the animation (which means that the generated CSS classes are + * added and removed on the element). Once `$animateCss` is called it will return an object with the following properties: + * + * ```js + * var animation = $animateCss(element, { ... }); + * ``` + * + * Now what do the contents of our `animation` variable look like: + * + * ```js + * { + * // starts the animation + * start: Function, + * + * // ends (aborts) the animation + * end: Function, + * + * // the total number of seconds that the animation will run for + * duration: Number, + * + * // the total number of seconds that the animation will delay for before starting + * delay: Number, + * + * // whether or not transitions were detected and will therefore be used for the animation + * transitions: Boolean, + * + * // whether or not keyframe animations were detected and will therefore be used for the animation + * keyframes: Boolean + * } + * ``` + * + * To actually start the animation we need to run `animation.start()` which will then return a promise that we can hook into to detect when the animation ends. + * If we choose not to run the animation then we MUST run `animation.end()` to perform a cleanup on the element (since some CSS classes and stlyes may have been + * applied to the element during the preparation phase). Note that all other properties such as duration, delay, transitions and keyframes are just properties + * and that changing them will not reconfigure the parameters of the animation. + * + * By calling `animation.start()` we do get back a promise, however, due to the nature of animations we may not want to tap into the default behaviour of + * animations (since they cause a digest to occur which may slow down the animation performance-wise). Therefore instead of calling `then` to capture when + * the animation ends be sure to call `done(callback)` (this is the recommended way to use `$animateCss` within JavaScript-animations). + * + * The example below should put this into perspective: + * + * ```js + * var animation = $animateCss(element, { ... }); + * + * // remember that if there is no CSS animation detected on the element + * // then the value returned from $animateCss will be null + * if (animation) { + * animation.start().done(function() { + * // yaay the animation is over + * doneCallback(); + * }); + * } else { + * doneCallback(); + * } + * ``` + * + * @param {DOMElement} element the element that will be animated + * @param {object} options the animation-related options that will be applied during the animation + * + * * `event` - The DOM event (e.g. enter, leave, move). When used, a generated CSS class of `ng-EVENT` and `ng-EVENT-active` will be applied + * to the element during the animation. Multiple events can be provided when spaces are used as a separator. (Note that this will not perform any DOM operation.) + * * `easing` - The CSS easing value that will be applied to the transition or keyframe animation (or both). + * * `transition` - The raw CSS transition style that will be used (e.g. `1s linear all`). + * * `keyframe` - The raw CSS keyframe animation style that will be used (e.g. `1s my_animation linear`). + * * `from` - The starting CSS styles (a key/value object) that will be applied at the start of the animation. + * * `to` - The ending CSS styles (a key/value object) that will be applied across the animation via a CSS transition. + * * `addClass` - A space separated list of CSS classes that will be added to the element and spread across the animation. + * * `removeClass` - A space separated list of CSS classes that will be removed from the element and spread across the animation. + * * `duration` - A number value representing the total duration of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `0` + * is provided then the animation will be skipped entirely. + * * `delay` - A number value representing the total delay of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `true` is + * used then whatever delay value is detected from the CSS classes will be mirrored on the elements styles (e.g. by setting delay true then the style value + * of the element will be `transition-delay: DETECTED_VALUE`). Using `true` is useful when you want the CSS classes and inline styles to all share the same + * CSS delay value. + * * `stagger` - A numeric time value representing the delay between successively animated elements + * ({@link ngAnimate#css-staggering-animations Click here to learn how CSS-based staggering works in ngAnimate.}) + * * `staggerIndex` - The numeric index representing the stagger item (e.g. a value of 5 is equal to the sixth item in the stagger; therefore when a + * `stagger` option value of `0.1` is used then there will be a stagger delay of `600ms`) + * + * @return {null|object} an object with a start method and details about the animation. If no animation is detected then a value of `null` will be returned. + * + * * `start` - The method to start the animation. This will return a `Promise` when called. + * * `end` - This method will cancel the animation and remove all applied CSS classes and styles. + */ + +// Detect proper transitionend/animationend event names. +var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT; + +// If unprefixed events are not supported but webkit-prefixed are, use the latter. +// Otherwise, just use W3C names, browsers not supporting them at all will just ignore them. +// Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend` +// but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`. +// Register both events in case `window.onanimationend` is not supported because of that, +// do the same for `transitionend` as Safari is likely to exhibit similar behavior. +// Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit +// therefore there is no reason to test anymore for other vendor prefixes: +// http://caniuse.com/#search=transition +if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) { + CSS_PREFIX = '-webkit-'; + TRANSITION_PROP = 'WebkitTransition'; + TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend'; +} else { + TRANSITION_PROP = 'transition'; + TRANSITIONEND_EVENT = 'transitionend'; +} + +if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) { + CSS_PREFIX = '-webkit-'; + ANIMATION_PROP = 'WebkitAnimation'; + ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend'; +} else { + ANIMATION_PROP = 'animation'; + ANIMATIONEND_EVENT = 'animationend'; +} + +var DURATION_KEY = 'Duration'; +var PROPERTY_KEY = 'Property'; +var DELAY_KEY = 'Delay'; +var TIMING_KEY = 'TimingFunction'; +var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount'; +var ANIMATION_PLAYSTATE_KEY = 'PlayState'; +var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3; +var CLOSING_TIME_BUFFER = 1.5; +var ONE_SECOND = 1000; +var BASE_TEN = 10; + +var SAFE_FAST_FORWARD_DURATION_VALUE = 9999; + +var ANIMATION_DELAY_PROP = ANIMATION_PROP + DELAY_KEY; +var ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY; + +var TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY; +var TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY; + +var DETECT_CSS_PROPERTIES = { + transitionDuration: TRANSITION_DURATION_PROP, + transitionDelay: TRANSITION_DELAY_PROP, + transitionProperty: TRANSITION_PROP + PROPERTY_KEY, + animationDuration: ANIMATION_DURATION_PROP, + animationDelay: ANIMATION_DELAY_PROP, + animationIterationCount: ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY +}; + +var DETECT_STAGGER_CSS_PROPERTIES = { + transitionDuration: TRANSITION_DURATION_PROP, + transitionDelay: TRANSITION_DELAY_PROP, + animationDuration: ANIMATION_DURATION_PROP, + animationDelay: ANIMATION_DELAY_PROP +}; + +function computeCssStyles($window, element, properties) { + var styles = Object.create(null); + var detectedStyles = $window.getComputedStyle(element) || {}; + forEach(properties, function(formalStyleName, actualStyleName) { + var val = detectedStyles[formalStyleName]; + if (val) { + var c = val.charAt(0); + + // only numerical-based values have a negative sign or digit as the first value + if (c === '-' || c === '+' || c >= 0) { + val = parseMaxTime(val); + } + + // by setting this to null in the event that the delay is not set or is set directly as 0 + // then we can still allow for zegative values to be used later on and not mistake this + // value for being greater than any other negative value. + if (val === 0) { + val = null; + } + styles[actualStyleName] = val; + } + }); + + return styles; +} + +function parseMaxTime(str) { + var maxValue = 0; + var values = str.split(/\s*,\s*/); + forEach(values, function(value) { + // it's always safe to consider only second values and omit `ms` values since + // getComputedStyle will always handle the conversion for us + if (value.charAt(value.length - 1) == 's') { + value = value.substring(0, value.length - 1); + } + value = parseFloat(value) || 0; + maxValue = maxValue ? Math.max(value, maxValue) : value; + }); + return maxValue; +} + +function truthyTimingValue(val) { + return val === 0 || val != null; +} + +function getCssTransitionDurationStyle(duration, applyOnlyDuration) { + var style = TRANSITION_PROP; + var value = duration + 's'; + if (applyOnlyDuration) { + style += DURATION_KEY; + } else { + value += ' linear all'; + } + return [style, value]; +} + +function getCssKeyframeDurationStyle(duration) { + return [ANIMATION_DURATION_PROP, duration + 's']; +} + +function getCssDelayStyle(delay, isKeyframeAnimation) { + var prop = isKeyframeAnimation ? ANIMATION_DELAY_PROP : TRANSITION_DELAY_PROP; + return [prop, delay + 's']; +} + +function blockTransitions(node, duration) { + // we use a negative delay value since it performs blocking + // yet it doesn't kill any existing transitions running on the + // same element which makes this safe for class-based animations + var value = duration ? '-' + duration + 's' : ''; + applyInlineStyle(node, [TRANSITION_DELAY_PROP, value]); + return [TRANSITION_DELAY_PROP, value]; +} + +function blockKeyframeAnimations(node, applyBlock) { + var value = applyBlock ? 'paused' : ''; + var key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY; + applyInlineStyle(node, [key, value]); + return [key, value]; +} + +function applyInlineStyle(node, styleTuple) { + var prop = styleTuple[0]; + var value = styleTuple[1]; + node.style[prop] = value; +} + +function createLocalCacheLookup() { + var cache = Object.create(null); + return { + flush: function() { + cache = Object.create(null); + }, + + count: function(key) { + var entry = cache[key]; + return entry ? entry.total : 0; + }, + + get: function(key) { + var entry = cache[key]; + return entry && entry.value; + }, + + put: function(key, value) { + if (!cache[key]) { + cache[key] = { total: 1, value: value }; + } else { + cache[key].total++; + } + } + }; +} + +var $AnimateCssProvider = ['$animateProvider', function($animateProvider) { + var gcsLookup = createLocalCacheLookup(); + var gcsStaggerLookup = createLocalCacheLookup(); + + this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout', + '$document', '$sniffer', '$$rAF', + function($window, $$jqLite, $$AnimateRunner, $timeout, + $document, $sniffer, $$rAF) { + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + var parentCounter = 0; + function gcsHashFn(node, extraClasses) { + var KEY = "$$ngAnimateParentKey"; + var parentNode = node.parentNode; + var parentID = parentNode[KEY] || (parentNode[KEY] = ++parentCounter); + return parentID + '-' + node.getAttribute('class') + '-' + extraClasses; + } + + function computeCachedCssStyles(node, className, cacheKey, properties) { + var timings = gcsLookup.get(cacheKey); + + if (!timings) { + timings = computeCssStyles($window, node, properties); + if (timings.animationIterationCount === 'infinite') { + timings.animationIterationCount = 1; + } + } + + // we keep putting this in multiple times even though the value and the cacheKey are the same + // because we're keeping an interal tally of how many duplicate animations are detected. + gcsLookup.put(cacheKey, timings); + return timings; + } + + function computeCachedCssStaggerStyles(node, className, cacheKey, properties) { + var stagger; + + // if we have one or more existing matches of matching elements + // containing the same parent + CSS styles (which is how cacheKey works) + // then staggering is possible + if (gcsLookup.count(cacheKey) > 0) { + stagger = gcsStaggerLookup.get(cacheKey); + + if (!stagger) { + var staggerClassName = pendClasses(className, '-stagger'); + + $$jqLite.addClass(node, staggerClassName); + + stagger = computeCssStyles($window, node, properties); + + // force the conversion of a null value to zero incase not set + stagger.animationDuration = Math.max(stagger.animationDuration, 0); + stagger.transitionDuration = Math.max(stagger.transitionDuration, 0); + + $$jqLite.removeClass(node, staggerClassName); + + gcsStaggerLookup.put(cacheKey, stagger); + } + } + + return stagger || {}; + } + + var bod = $document[0].body; + var cancelLastRAFRequest; + var rafWaitQueue = []; + function waitUntilQuiet(callback) { + if (cancelLastRAFRequest) { + cancelLastRAFRequest(); //cancels the request + } + rafWaitQueue.push(callback); + cancelLastRAFRequest = $$rAF(function() { + cancelLastRAFRequest = null; + gcsLookup.flush(); + gcsStaggerLookup.flush(); + + //the line below will force the browser to perform a repaint so + //that all the animated elements within the animation frame will + //be properly updated and drawn on screen. This is required to + //ensure that the preparation animation is properly flushed so that + //the active state picks up from there. DO NOT REMOVE THIS LINE. + //DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH + //WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND + //WILL TAKE YEARS AWAY FROM YOUR LIFE. + var width = bod.offsetWidth + 1; + forEach(rafWaitQueue, function(cb) { + cb(width); + }); + rafWaitQueue.length = 0; + }); + } + + return init; + + function computeTimings(node, className, cacheKey) { + var timings = computeCachedCssStyles(node, className, cacheKey, DETECT_CSS_PROPERTIES); + var aD = timings.animationDelay; + var tD = timings.transitionDelay; + timings.maxDelay = aD && tD + ? Math.max(aD, tD) + : (aD || tD); + timings.maxDuration = Math.max( + timings.animationDuration * timings.animationIterationCount, + timings.transitionDuration); + + return timings; + } + + function init(element, options) { + var node = element[0]; + options = prepareAnimationOptions(options); + + var temporaryStyles = []; + var classes = element.attr('class'); + var styles = packageStyles(options); + var animationClosed; + var animationPaused; + var animationCompleted; + var runner; + var runnerHost; + var maxDelay; + var maxDelayTime; + var maxDuration; + var maxDurationTime; + + if (options.duration === 0 || (!$sniffer.animations && !$sniffer.transitions)) { + close(); + return; + } + + var method = options.event && isArray(options.event) + ? options.event.join(' ') + : options.event; + + var isStructural = method && options.structural; + var structuralClassName = ''; + var addRemoveClassName = ''; + + if (isStructural) { + structuralClassName = pendClasses(method, 'ng-', true); + } else if (method) { + structuralClassName = method; + } + + if (options.addClass) { + addRemoveClassName += pendClasses(options.addClass, '-add'); + } + + if (options.removeClass) { + if (addRemoveClassName.length) { + addRemoveClassName += ' '; + } + addRemoveClassName += pendClasses(options.removeClass, '-remove'); + } + + var setupClasses = [structuralClassName, addRemoveClassName].join(' ').trim(); + var fullClassName = classes + ' ' + setupClasses; + var activeClasses = pendClasses(setupClasses, '-active'); + var hasToStyles = styles.to && Object.keys(styles.to).length > 0; + + // there is no way we can trigger an animation since no styles and + // no classes are being applied which would then trigger a transition + if (!hasToStyles && !setupClasses) { + close(); + return false; + } + + var cacheKey, stagger; + if (options.stagger > 0) { + var staggerVal = parseFloat(options.stagger); + stagger = { + transitionDelay: staggerVal, + animationDelay: staggerVal, + transitionDuration: 0, + animationDuration: 0 + }; + } else { + cacheKey = gcsHashFn(node, fullClassName); + stagger = computeCachedCssStaggerStyles(node, setupClasses, cacheKey, DETECT_STAGGER_CSS_PROPERTIES); + } + + $$jqLite.addClass(element, setupClasses); + + var applyOnlyDuration; + + if (options.transitionStyle) { + var transitionStyle = [TRANSITION_PROP, options.transitionStyle]; + applyInlineStyle(node, transitionStyle); + temporaryStyles.push(transitionStyle); + } + + if (options.duration >= 0) { + applyOnlyDuration = node.style[TRANSITION_PROP].length > 0; + var durationStyle = getCssTransitionDurationStyle(options.duration, applyOnlyDuration); + + // we set the duration so that it will be picked up by getComputedStyle later + applyInlineStyle(node, durationStyle); + temporaryStyles.push(durationStyle); + } + + if (options.keyframeStyle) { + var keyframeStyle = [ANIMATION_PROP, options.keyframeStyle]; + applyInlineStyle(node, keyframeStyle); + temporaryStyles.push(keyframeStyle); + } + + var itemIndex = stagger + ? options.staggerIndex >= 0 + ? options.staggerIndex + : gcsLookup.count(cacheKey) + : 0; + + var isFirst = itemIndex === 0; + + // this is a pre-emptive way of forcing the setup classes to be added and applied INSTANTLY + // without causing any combination of transitions to kick in. By adding a negative delay value + // it forces the setup class' transition to end immediately. We later then remove the negative + // transition delay to allow for the transition to naturally do it's thing. The beauty here is + // that if there is no transition defined then nothing will happen and this will also allow + // other transitions to be stacked on top of each other without any chopping them out. + if (isFirst) { + blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE); + } + + var timings = computeTimings(node, fullClassName, cacheKey); + var relativeDelay = timings.maxDelay; + maxDelay = Math.max(relativeDelay, 0); + maxDuration = timings.maxDuration; + + var flags = {}; + flags.hasTransitions = timings.transitionDuration > 0; + flags.hasAnimations = timings.animationDuration > 0; + flags.hasTransitionAll = flags.hasTransitions && timings.transitionProperty == 'all'; + flags.applyTransitionDuration = hasToStyles && ( + (flags.hasTransitions && !flags.hasTransitionAll) + || (flags.hasAnimations && !flags.hasTransitions)); + flags.applyAnimationDuration = options.duration && flags.hasAnimations; + flags.applyTransitionDelay = truthyTimingValue(options.delay) && (flags.applyTransitionDuration || flags.hasTransitions); + flags.applyAnimationDelay = truthyTimingValue(options.delay) && flags.hasAnimations; + flags.recalculateTimingStyles = addRemoveClassName.length > 0; + + if (flags.applyTransitionDuration || flags.applyAnimationDuration) { + maxDuration = options.duration ? parseFloat(options.duration) : maxDuration; + + if (flags.applyTransitionDuration) { + flags.hasTransitions = true; + timings.transitionDuration = maxDuration; + applyOnlyDuration = node.style[TRANSITION_PROP + PROPERTY_KEY].length > 0; + temporaryStyles.push(getCssTransitionDurationStyle(maxDuration, applyOnlyDuration)); + } + + if (flags.applyAnimationDuration) { + flags.hasAnimations = true; + timings.animationDuration = maxDuration; + temporaryStyles.push(getCssKeyframeDurationStyle(maxDuration)); + } + } + + flags.transitionClassBlock = timings.transitionProperty === 'none' && + timings.transitionDuration === 0; + + // there may be a situation where a structural animation is combined together + // with CSS classes that need to resolve before the animation is computed. + // However this means that there is no explicit CSS code to block the animation + // from happening (by setting 0s none in the class name). If this is the case + // we need to apply the classes before the first rAF so we know to continue if + // there actually is a detected transition or keyframe animation + var applyClassesEarly = maxDuration === 0 + && isStructural + && addRemoveClassName.length > 0 + && !flags.transitionClassBlock; + + // this is an early check to avoid having to do another call to getComputedStyle + // call which is expensive. GCS calls are cached to speed things up. + if (!applyClassesEarly && maxDuration === 0 && !flags.recalculateTimingStyles) { + close(); + return false; + } + + if (applyClassesEarly) { + applyAnimationClasses(element, options); + + // no need to calculate this anymore + flags.recalculateTimingStyles = false; + + fullClassName = node.className + ' ' + setupClasses; + cacheKey = gcsHashFn(node, fullClassName); + + timings = computeTimings(node, fullClassName, cacheKey); + relativeDelay = timings.maxDelay; + maxDelay = Math.max(relativeDelay, 0); + maxDuration = timings.maxDuration; + } + + if (maxDuration === 0 && !flags.recalculateTimingStyles) { + close(); + return false; + } + + // we need to recalculate the delay value since we used a pre-emptive negative + // delay value and the delay value is required for the final event checking. This + // property will ensure that this will happen after the RAF phase has passed. + if (timings.transitionDuration > 0) { + flags.recalculateTimingStyles = flags.recalculateTimingStyles || isFirst; + } + + maxDelayTime = maxDelay * ONE_SECOND; + maxDurationTime = maxDuration * ONE_SECOND; + if (!options.skipBlocking) { + flags.blockTransition = timings.transitionDuration > 0; + flags.blockKeyframeAnimation = timings.animationDuration > 0 && + stagger.animationDelay > 0 && + stagger.animationDuration === 0; + } + + if (flags.blockTransition) { + applyAnimationFromStyles(element, options); + } else { + blockTransitions(node, false); + } + + applyBlocking(maxDuration); + + // TODO(matsko): for 1.5 change this code to have an animator object for better debugging + return { + end: endFn, + start: function() { + if (animationClosed) return; + + runnerHost = { + end: endFn, + cancel: cancelFn, + resume: null, //this will be set during the start() phase + pause: null + }; + + runner = new $$AnimateRunner(runnerHost); + + waitUntilQuiet(start); + + // we don't have access to pause/resume the animation + // since it hasn't run yet. AnimateRunner will therefore + // set noop functions for resume and pause and they will + // later be overridden once the animation is triggered + return runner; + } + }; + + function endFn() { + close(); + } + + function cancelFn() { + close(true); + } + + function close(rejected) { // jshint ignore:line + // if the promise has been called already then we shouldn't close + // the animation again + if (animationClosed || (animationCompleted && animationPaused)) return; + animationClosed = true; + animationPaused = false; + + $$jqLite.removeClass(element, setupClasses); + $$jqLite.removeClass(element, activeClasses); + + blockKeyframeAnimations(node, false); + blockTransitions(node, false); + + forEach(temporaryStyles, function(entry) { + // There is only one way to remove inline style properties entirely from elements. + // By using `removeProperty` this works, but we need to convert camel-cased CSS + // styles down to hyphenated values. + node.style[entry[0]] = ''; + }); + + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + + // the reason why we have this option is to allow a synchronous closing callback + // that is fired as SOON as the animation ends (when the CSS is removed) or if + // the animation never takes off at all. A good example is a leave animation since + // the element must be removed just after the animation is over or else the element + // will appear on screen for one animation frame causing an overbearing flicker. + if (options.onDone) { + options.onDone(); + } + + // if the preparation function fails then the promise is not setup + if (runner) { + runner.complete(!rejected); + } + } + + function applyBlocking(duration) { + if (flags.blockTransition) { + blockTransitions(node, duration); + } + + if (flags.blockKeyframeAnimation) { + blockKeyframeAnimations(node, !!duration); + } + } + + function start() { + if (animationClosed) return; + + var startTime, events = []; + + // even though we only pause keyframe animations here the pause flag + // will still happen when transitions are used. Only the transition will + // not be paused since that is not possible. If the animation ends when + // paused then it will not complete until unpaused or cancelled. + var playPause = function(playAnimation) { + if (!animationCompleted) { + animationPaused = !playAnimation; + if (timings.animationDuration) { + var value = blockKeyframeAnimations(node, animationPaused); + animationPaused + ? temporaryStyles.push(value) + : removeFromArray(temporaryStyles, value); + } + } else if (animationPaused && playAnimation) { + animationPaused = false; + close(); + } + }; + + // checking the stagger duration prevents an accidently cascade of the CSS delay style + // being inherited from the parent. If the transition duration is zero then we can safely + // rely that the delay value is an intential stagger delay style. + var maxStagger = itemIndex > 0 + && ((timings.transitionDuration && stagger.transitionDuration === 0) || + (timings.animationDuration && stagger.animationDuration === 0)) + && Math.max(stagger.animationDelay, stagger.transitionDelay); + if (maxStagger) { + $timeout(triggerAnimationStart, + Math.floor(maxStagger * itemIndex * ONE_SECOND), + false); + } else { + triggerAnimationStart(); + } + + // this will decorate the existing promise runner with pause/resume methods + runnerHost.resume = function() { + playPause(true); + }; + + runnerHost.pause = function() { + playPause(false); + }; + + function triggerAnimationStart() { + // just incase a stagger animation kicks in when the animation + // itself was cancelled entirely + if (animationClosed) return; + + applyBlocking(false); + + forEach(temporaryStyles, function(entry) { + var key = entry[0]; + var value = entry[1]; + node.style[key] = value; + }); + + applyAnimationClasses(element, options); + $$jqLite.addClass(element, activeClasses); + + if (flags.recalculateTimingStyles) { + fullClassName = node.className + ' ' + setupClasses; + cacheKey = gcsHashFn(node, fullClassName); + + timings = computeTimings(node, fullClassName, cacheKey); + relativeDelay = timings.maxDelay; + maxDelay = Math.max(relativeDelay, 0); + maxDuration = timings.maxDuration; + + if (maxDuration === 0) { + close(); + return; + } + + flags.hasTransitions = timings.transitionDuration > 0; + flags.hasAnimations = timings.animationDuration > 0; + } + + if (flags.applyTransitionDelay || flags.applyAnimationDelay) { + relativeDelay = typeof options.delay !== "boolean" && truthyTimingValue(options.delay) + ? parseFloat(options.delay) + : relativeDelay; + + maxDelay = Math.max(relativeDelay, 0); + + var delayStyle; + if (flags.applyTransitionDelay) { + timings.transitionDelay = relativeDelay; + delayStyle = getCssDelayStyle(relativeDelay); + temporaryStyles.push(delayStyle); + node.style[delayStyle[0]] = delayStyle[1]; + } + + if (flags.applyAnimationDelay) { + timings.animationDelay = relativeDelay; + delayStyle = getCssDelayStyle(relativeDelay, true); + temporaryStyles.push(delayStyle); + node.style[delayStyle[0]] = delayStyle[1]; + } + } + + maxDelayTime = maxDelay * ONE_SECOND; + maxDurationTime = maxDuration * ONE_SECOND; + + if (options.easing) { + var easeProp, easeVal = options.easing; + if (flags.hasTransitions) { + easeProp = TRANSITION_PROP + TIMING_KEY; + temporaryStyles.push([easeProp, easeVal]); + node.style[easeProp] = easeVal; + } + if (flags.hasAnimations) { + easeProp = ANIMATION_PROP + TIMING_KEY; + temporaryStyles.push([easeProp, easeVal]); + node.style[easeProp] = easeVal; + } + } + + if (timings.transitionDuration) { + events.push(TRANSITIONEND_EVENT); + } + + if (timings.animationDuration) { + events.push(ANIMATIONEND_EVENT); + } + + startTime = Date.now(); + element.on(events.join(' '), onAnimationProgress); + $timeout(onAnimationExpired, maxDelayTime + CLOSING_TIME_BUFFER * maxDurationTime); + + applyAnimationToStyles(element, options); + } + + function onAnimationExpired() { + // although an expired animation is a failed animation, getting to + // this outcome is very easy if the CSS code screws up. Therefore we + // should still continue normally as if the animation completed correctly. + close(); + } + + function onAnimationProgress(event) { + event.stopPropagation(); + var ev = event.originalEvent || event; + var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now(); + + /* Firefox (or possibly just Gecko) likes to not round values up + * when a ms measurement is used for the animation */ + var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES)); + + /* $manualTimeStamp is a mocked timeStamp value which is set + * within browserTrigger(). This is only here so that tests can + * mock animations properly. Real events fallback to event.timeStamp, + * or, if they don't, then a timeStamp is automatically created for them. + * We're checking to see if the timeStamp surpasses the expected delay, + * but we're using elapsedTime instead of the timeStamp on the 2nd + * pre-condition since animations sometimes close off early */ + if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) { + // we set this flag to ensure that if the transition is paused then, when resumed, + // the animation will automatically close itself since transitions cannot be paused. + animationCompleted = true; + close(); + } + } + } + } + }]; +}]; diff --git a/src/ngAnimate/animateCssDriver.js b/src/ngAnimate/animateCssDriver.js new file mode 100644 index 000000000000..f0e2fdace984 --- /dev/null +++ b/src/ngAnimate/animateCssDriver.js @@ -0,0 +1,218 @@ +'use strict'; + +var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationProvider) { + $$animationProvider.drivers.push('$$animateCssDriver'); + + var NG_ANIMATE_SHIM_CLASS_NAME = 'ng-animate-shim'; + var NG_ANIMATE_ANCHOR_CLASS_NAME = 'ng-animate-anchor'; + var NG_ANIMATE_ANCHOR_SUFFIX = '-anchor'; + + var NG_OUT_ANCHOR_CLASS_NAME = 'ng-anchor-out'; + var NG_IN_ANCHOR_CLASS_NAME = 'ng-anchor-in'; + + this.$get = ['$animateCss', '$rootScope', '$$AnimateRunner', '$rootElement', '$document', '$sniffer', + function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $document, $sniffer) { + + // only browsers that support these properties can render animations + if (!$sniffer.animations && !$sniffer.transitions) return noop; + + var bodyNode = $document[0].body; + var rootNode = $rootElement[0]; + + var rootBodyElement = jqLite(bodyNode.parentNode === rootNode ? bodyNode : rootNode); + + return function initDriverFn(animationDetails) { + return animationDetails.from && animationDetails.to + ? prepareFromToAnchorAnimation(animationDetails.from, + animationDetails.to, + animationDetails.classes, + animationDetails.anchors) + : prepareRegularAnimation(animationDetails); + }; + + function filterCssClasses(classes) { + //remove all the `ng-` stuff + return classes.replace(/\bng-\S+\b/g, ''); + } + + function getUniqueValues(a, b) { + if (isString(a)) a = a.split(' '); + if (isString(b)) b = b.split(' '); + return a.filter(function(val) { + return b.indexOf(val) === -1; + }).join(' '); + } + + function prepareAnchoredAnimation(classes, outAnchor, inAnchor) { + var clone = jqLite(outAnchor[0].cloneNode(true)); + var startingClasses = filterCssClasses(clone.attr('class') || ''); + var anchorClasses = pendClasses(classes, NG_ANIMATE_ANCHOR_SUFFIX); + + outAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME); + inAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME); + + clone.addClass(NG_ANIMATE_ANCHOR_CLASS_NAME); + clone.addClass(anchorClasses); + + rootBodyElement.append(clone); + + var animatorOut = prepareOutAnimation(); + if (!animatorOut) { + return end(); + } + + return { + start: function() { + var runner; + + var currentAnimation = animatorOut.start(); + currentAnimation.done(function() { + currentAnimation = null; + var animatorIn = prepareInAnimation(); + if (animatorIn) { + currentAnimation = animatorIn.start(); + currentAnimation.done(function() { + currentAnimation = null; + end(); + runner.complete(); + }); + return currentAnimation; + } + // in the event that there is no `in` animation + end(); + runner.complete(); + }); + + runner = new $$AnimateRunner({ + end: endFn, + cancel: endFn + }); + + return runner; + + function endFn() { + if (currentAnimation) { + currentAnimation.end(); + } + } + } + }; + + function calculateAnchorStyles(anchor) { + var styles = {}; + + var coords = anchor[0].getBoundingClientRect(); + + // we iterate directly since safari messes up and doesn't return + // all the keys for the coods object when iterated + forEach(['width','height','top','left'], function(key) { + var value = coords[key]; + switch (key) { + case 'top': + value += bodyNode.scrollTop; + break; + case 'left': + value += bodyNode.scrollLeft; + break; + } + styles[key] = Math.floor(value) + 'px'; + }); + return styles; + } + + function prepareOutAnimation() { + return $animateCss(clone, { + addClass: NG_OUT_ANCHOR_CLASS_NAME, + delay: true, + from: calculateAnchorStyles(outAnchor) + }); + } + + function prepareInAnimation() { + var endingClasses = filterCssClasses(inAnchor.attr('class')); + var classes = getUniqueValues(endingClasses, startingClasses); + return $animateCss(clone, { + to: calculateAnchorStyles(inAnchor), + addClass: NG_IN_ANCHOR_CLASS_NAME + ' ' + classes, + removeClass: NG_OUT_ANCHOR_CLASS_NAME + ' ' + startingClasses, + delay: true + }); + } + + function end() { + clone.remove(); + outAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME); + inAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME); + } + } + + function prepareFromToAnchorAnimation(from, to, classes, anchors) { + var fromAnimation = prepareRegularAnimation(from); + var toAnimation = prepareRegularAnimation(to); + + var anchorAnimations = []; + forEach(anchors, function(anchor) { + var outElement = anchor['out']; + var inElement = anchor['in']; + var animator = prepareAnchoredAnimation(classes, outElement, inElement); + if (animator) { + anchorAnimations.push(animator); + } + }); + + // no point in doing anything when there are no elements to animate + if (!fromAnimation && !toAnimation && anchorAnimations.length === 0) return; + + return { + start: function() { + var animationRunners = []; + + if (fromAnimation) { + animationRunners.push(fromAnimation.start()); + } + + if (toAnimation) { + animationRunners.push(toAnimation.start()); + } + + forEach(anchorAnimations, function(animation) { + animationRunners.push(animation.start()); + }); + + var runner = new $$AnimateRunner({ + end: endFn, + cancel: endFn // CSS-driven animations cannot be cancelled, only ended + }); + + $$AnimateRunner.all(animationRunners, function(status) { + runner.complete(status); + }); + + return runner; + + function endFn() { + forEach(animationRunners, function(runner) { + runner.end(); + }); + } + } + }; + } + + function prepareRegularAnimation(animationDetails) { + var element = animationDetails.element; + var options = animationDetails.options || {}; + options.structural = animationDetails.structural; + + // we special case the leave animation since we want to ensure that + // the element is removed as soon as the animation is over. Otherwise + // a flicker might appear or the element may not be removed at all + options.event = animationDetails.event; + if (options.event === 'leave' && animationDetails.domOperation) { + options.onDone = animationDetails.domOperation; + } + + return $animateCss(element, options); + } + }]; +}]; diff --git a/src/ngAnimate/animateJs.js b/src/ngAnimate/animateJs.js new file mode 100644 index 000000000000..4395fbf9f81c --- /dev/null +++ b/src/ngAnimate/animateJs.js @@ -0,0 +1,250 @@ +'use strict'; + +// TODO(matsko): use caching here to speed things up for detection +// TODO(matsko): add documentation +// by the time... + +var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) { + this.$get = ['$injector', '$$AnimateRunner', '$$rAFMutex', '$$jqLite', + function($injector, $$AnimateRunner, $$rAFMutex, $$jqLite) { + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + // $animateJs(element, 'enter'); + return function(element, event, classes, options) { + // the `classes` argument is optional and if it is not used + // then the classes will be resolved from the element's className + // property as well as options.addClass/options.removeClass. + if (arguments.length === 3 && isObject(classes)) { + options = classes; + classes = null; + } + + options = prepareAnimationOptions(options); + if (!classes) { + classes = element.attr('class') || ''; + if (options.addClass) { + classes += ' ' + options.addClass; + } + if (options.removeClass) { + classes += ' ' + options.removeClass; + } + } + + var classesToAdd = options.addClass; + var classesToRemove = options.removeClass; + + // the lookupAnimations function returns a series of animation objects that are + // matched up with one or more of the CSS classes. These animation objects are + // defined via the module.animation factory function. If nothing is detected then + // we don't return anything which then makes $animation query the next driver. + var animations = lookupAnimations(classes); + var before, after; + if (animations.length) { + var afterFn, beforeFn; + if (event == 'leave') { + beforeFn = 'leave'; + afterFn = 'afterLeave'; // TODO(matsko): get rid of this + } else { + beforeFn = 'before' + event.charAt(0).toUpperCase() + event.substr(1); + afterFn = event; + } + + if (event !== 'enter' && event !== 'move') { + before = packageAnimations(element, event, options, animations, beforeFn); + } + after = packageAnimations(element, event, options, animations, afterFn); + } + + // no matching animations + if (!before && !after) return; + + function applyOptions() { + options.domOperation(); + applyAnimationClasses(element, options); + } + + return { + start: function() { + var closeActiveAnimations; + var chain = []; + + if (before) { + chain.push(function(fn) { + closeActiveAnimations = before(fn); + }); + } + + if (chain.length) { + chain.push(function(fn) { + applyOptions(); + fn(true); + }); + } else { + applyOptions(); + } + + if (after) { + chain.push(function(fn) { + closeActiveAnimations = after(fn); + }); + } + + var animationClosed = false; + var runner = new $$AnimateRunner({ + end: function() { + endAnimations(); + }, + cancel: function() { + endAnimations(true); + } + }); + + $$AnimateRunner.chain(chain, onComplete); + return runner; + + function onComplete(success) { + animationClosed = true; + applyOptions(); + applyAnimationStyles(element, options); + runner.complete(success); + } + + function endAnimations(cancelled) { + if (!animationClosed) { + (closeActiveAnimations || noop)(cancelled); + onComplete(cancelled); + } + } + } + }; + + function executeAnimationFn(fn, element, event, options, onDone) { + var args; + switch (event) { + case 'animate': + args = [element, options.from, options.to, onDone]; + break; + + case 'setClass': + args = [element, classesToAdd, classesToRemove, onDone]; + break; + + case 'addClass': + args = [element, classesToAdd, onDone]; + break; + + case 'removeClass': + args = [element, classesToRemove, onDone]; + break; + + default: + args = [element, onDone]; + break; + } + + args.push(options); + + var value = fn.apply(fn, args); + + // optional onEnd / onCancel callback + return isFunction(value) ? value : noop; + } + + function groupEventedAnimations(element, event, options, animations, fnName) { + var operations = []; + forEach(animations, function(ani) { + var animation = ani[fnName]; + if (!animation) return; + + // note that all of these animations will run in parallel + operations.push(function() { + var runner; + var endProgressCb; + + var resolved = false; + var onAnimationComplete = function(rejected) { + if (!resolved) { + resolved = true; + (endProgressCb || noop)(rejected); + runner.complete(!rejected); + } + }; + + runner = new $$AnimateRunner({ + end: function() { + onAnimationComplete(); + }, + cancel: function() { + onAnimationComplete(true); + } + }); + + endProgressCb = executeAnimationFn(animation, element, event, options, function(result) { + var cancelled = result === false; + onAnimationComplete(cancelled); + }); + + return runner; + }); + }); + + return operations; + } + + function packageAnimations(element, event, options, animations, fnName) { + var operations = groupEventedAnimations(element, event, options, animations, fnName); + if (operations.length === 0) { + var a,b; + if (fnName === 'beforeSetClass') { + a = groupEventedAnimations(element, 'removeClass', options, animations, 'beforeRemoveClass'); + b = groupEventedAnimations(element, 'addClass', options, animations, 'beforeAddClass'); + } else if (fnName === 'setClass') { + a = groupEventedAnimations(element, 'removeClass', options, animations, 'removeClass'); + b = groupEventedAnimations(element, 'addClass', options, animations, 'addClass'); + } + + if (a) { + operations = operations.concat(a); + } + if (b) { + operations = operations.concat(b); + } + } + + if (operations.length === 0) return; + + // TODO(matsko): add documentation + return function startAnimation(callback) { + var runners = []; + if (operations.length) { + forEach(operations, function(animateFn) { + runners.push(animateFn()); + }); + } + + runners.length ? $$AnimateRunner.all(runners, callback) : callback(); + + return function endFn(reject) { + forEach(runners, function(runner) { + reject ? runner.cancel() : runner.end(); + }); + }; + }; + } + }; + + function lookupAnimations(classes) { + classes = isArray(classes) ? classes : classes.split(' '); + var matches = [], flagMap = {}; + for (var i=0; i < classes.length; i++) { + var klass = classes[i], + animationFactory = $animateProvider.$$registeredAnimations[klass]; + if (animationFactory && !flagMap[klass]) { + matches.push($injector.get(animationFactory)); + flagMap[klass] = true; + } + } + return matches; + } + }]; +}]; diff --git a/src/ngAnimate/animateJsDriver.js b/src/ngAnimate/animateJsDriver.js new file mode 100644 index 000000000000..bba970456872 --- /dev/null +++ b/src/ngAnimate/animateJsDriver.js @@ -0,0 +1,61 @@ +'use strict'; + +var $$AnimateJsDriverProvider = ['$$animationProvider', function($$animationProvider) { + $$animationProvider.drivers.push('$$animateJsDriver'); + this.$get = ['$$animateJs', '$$AnimateRunner', function($$animateJs, $$AnimateRunner) { + return function initDriverFn(animationDetails) { + if (animationDetails.from && animationDetails.to) { + var fromAnimation = prepareAnimation(animationDetails.from); + var toAnimation = prepareAnimation(animationDetails.to); + if (!fromAnimation && !toAnimation) return; + + return { + start: function() { + var animationRunners = []; + + if (fromAnimation) { + animationRunners.push(fromAnimation.start()); + } + + if (toAnimation) { + animationRunners.push(toAnimation.start()); + } + + $$AnimateRunner.all(animationRunners, done); + + var runner = new $$AnimateRunner({ + end: endFnFactory(), + cancel: endFnFactory() + }); + + return runner; + + function endFnFactory() { + return function() { + forEach(animationRunners, function(runner) { + // at this point we cannot cancel animations for groups just yet. 1.5+ + runner.end(); + }); + }; + } + + function done(status) { + runner.complete(status); + } + } + }; + } else { + return prepareAnimation(animationDetails); + } + }; + + function prepareAnimation(animationDetails) { + // TODO(matsko): make sure to check for grouped animations and delegate down to normal animations + var element = animationDetails.element; + var event = animationDetails.event; + var options = animationDetails.options; + var classes = animationDetails.classes; + return $$animateJs(element, event, classes, options); + } + }]; +}]; diff --git a/src/ngAnimate/animateQueue.js b/src/ngAnimate/animateQueue.js new file mode 100644 index 000000000000..3d5b58f27fc5 --- /dev/null +++ b/src/ngAnimate/animateQueue.js @@ -0,0 +1,551 @@ +'use strict'; + +var NG_ANIMATE_ATTR_NAME = 'data-ng-animate'; +var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { + var PRE_DIGEST_STATE = 1; + var RUNNING_STATE = 2; + + var rules = this.rules = { + skip: [], + cancel: [], + join: [] + }; + + function isAllowed(ruleType, element, currentAnimation, previousAnimation) { + return rules[ruleType].some(function(fn) { + return fn(element, currentAnimation, previousAnimation); + }); + } + + function hasAnimationClasses(options, and) { + options = options || {}; + var a = (options.addClass || '').length > 0; + var b = (options.removeClass || '').length > 0; + return and ? a && b : a || b; + } + + rules.join.push(function(element, newAnimation, currentAnimation) { + // if the new animation is class-based then we can just tack that on + return !newAnimation.structural && hasAnimationClasses(newAnimation.options); + }); + + rules.skip.push(function(element, newAnimation, currentAnimation) { + // there is no need to animate anything if no classes are being added and + // there is no structural animation that will be triggered + return !newAnimation.structural && !hasAnimationClasses(newAnimation.options); + }); + + rules.skip.push(function(element, newAnimation, currentAnimation) { + // why should we trigger a new structural animation if the element will + // be removed from the DOM anyway? + return currentAnimation.event == 'leave' && newAnimation.structural; + }); + + rules.skip.push(function(element, newAnimation, currentAnimation) { + // if there is a current animation then skip the class-based animation + return currentAnimation.structural && !newAnimation.structural; + }); + + rules.cancel.push(function(element, newAnimation, currentAnimation) { + // there can never be two structural animations running at the same time + return currentAnimation.structural && newAnimation.structural; + }); + + rules.cancel.push(function(element, newAnimation, currentAnimation) { + // if the previous animation is already running, but the new animation will + // be triggered, but the new animation is structural + return currentAnimation.state === RUNNING_STATE && newAnimation.structural; + }); + + this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$HashMap', + '$$animation', '$$AnimateRunner', '$templateRequest', '$$jqLite', + function($$rAF, $rootScope, $rootElement, $document, $$HashMap, + $$animation, $$AnimateRunner, $templateRequest, $$jqLite) { + + var activeAnimationsLookup = new $$HashMap(); + var disabledElementsLookup = new $$HashMap(); + + var animationsEnabled = null; + + // Wait until all directive and route-related templates are downloaded and + // compiled. The $templateRequest.totalPendingRequests variable keeps track of + // all of the remote templates being currently downloaded. If there are no + // templates currently downloading then the watcher will still fire anyway. + var deregisterWatch = $rootScope.$watch( + function() { return $templateRequest.totalPendingRequests === 0; }, + function(isEmpty) { + if (!isEmpty) return; + deregisterWatch(); + + // Now that all templates have been downloaded, $animate will wait until + // the post digest queue is empty before enabling animations. By having two + // calls to $postDigest calls we can ensure that the flag is enabled at the + // very end of the post digest queue. Since all of the animations in $animate + // use $postDigest, it's important that the code below executes at the end. + // This basically means that the page is fully downloaded and compiled before + // any animations are triggered. + $rootScope.$$postDigest(function() { + $rootScope.$$postDigest(function() { + // we check for null directly in the event that the application already called + // .enabled() with whatever arguments that it provided it with + if (animationsEnabled === null) { + animationsEnabled = true; + } + }); + }); + } + ); + + var bodyElement = jqLite($document[0].body); + + var callbackRegistry = {}; + + // remember that the classNameFilter is set during the provider/config + // stage therefore we can optimize here and setup a helper function + var classNameFilter = $animateProvider.classNameFilter(); + var isAnimatableClassName = !classNameFilter + ? function() { return true; } + : function(className) { + return classNameFilter.test(className); + }; + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + function normalizeAnimationOptions(element, options) { + return mergeAnimationOptions(element, options, {}); + } + + function findCallbacks(element, event) { + var targetNode = element[0]; + + var matches = []; + var entries = callbackRegistry[event]; + if (entries) { + forEach(entries, function(entry) { + if (entry.node.contains(targetNode)) { + matches.push(entry.callback); + } + }); + } + + return matches; + } + + function triggerCallback(event, element, phase, data) { + $$rAF(function() { + forEach(findCallbacks(element, event), function(callback) { + callback(element, phase, data); + }); + }); + } + + return { + on: function(event, container, callback) { + var node = extractElementNode(container); + callbackRegistry[event] = callbackRegistry[event] || []; + callbackRegistry[event].push({ + node: node, + callback: callback + }); + }, + + off: function(event, container, callback) { + var entries = callbackRegistry[event]; + if (!entries) return; + + callbackRegistry[event] = arguments.length === 1 + ? null + : filterFromRegistry(entries, container, callback); + + function filterFromRegistry(list, matchContainer, matchCallback) { + var containerNode = extractElementNode(matchContainer); + return list.filter(function(entry) { + var isMatch = entry.node === containerNode && + (!matchCallback || entry.callback === matchCallback); + return !isMatch; + }); + } + }, + + push: function(element, event, options, domOperation) { + options = options || {}; + options.domOperation = domOperation; + return queueAnimation(element, event, options); + }, + + // this method has four signatures: + // () - global getter + // (bool) - global setter + // (element) - element getter + // (element, bool) - element setter + enabled: function(element, bool) { + var argCount = arguments.length; + + if (argCount === 0) { + // () - Global getter + bool = !!animationsEnabled; + } else { + var hasElement = isElement(element); + + if (!hasElement) { + // (bool) - Global setter + bool = animationsEnabled = !!element; + } else { + var node = element.length ? element[0] : element; + var recordExists = disabledElementsLookup.get(node); + + if (argCount === 1) { + // (element) - Element getter + bool = !recordExists; + } else { + // (element, bool) - Element setter + bool = !!bool; + if (!bool) { + disabledElementsLookup.put(node, true); + } else if (recordExists) { + disabledElementsLookup.remove(node); + } + } + } + } + + return bool; + } + }; + + function queueAnimation(element, event, options) { + element = stripCommentsFromElement(element); + var node = element[0]; + + options = prepareAnimationOptions(options); + var parent = element.parent(); + + // we create a fake runner with a working promise. + // These methods will become available after the digest has passed + var runner = new $$AnimateRunner(); + + // there are situations where a directive issues an animation for + // a jqLite wrapper that contains only comment nodes... If this + // happens then there is no way we can perform an animation + if (!node) { + runner.end(); + return runner; + } + + if (isArray(options.addClass)) { + options.addClass = options.addClass.join(' '); + } + + if (isArray(options.removeClass)) { + options.removeClass = options.removeClass.join(' '); + } + + if (options.from && !isObject(options.from)) { + options.from = null; + } + + if (options.to && !isObject(options.to)) { + options.to = null; + } + + var className = [node.className, options.addClass, options.removeClass].join(' '); + if (!isAnimatableClassName(className)) { + runner.end(); + return runner; + } + + var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0; + + // this is a hard disable of all animations for the application or on + // the element itself, therefore there is no need to continue further + // past this point if not enabled + var skipAnimations = !animationsEnabled || disabledElementsLookup.get(node); + var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {}; + var hasExistingAnimation = !!existingAnimation.state; + + // there is no point in traversing the same collection of parent ancestors if a followup + // animation will be run on the same element that already did all that checking work + if (!skipAnimations && (!hasExistingAnimation || existingAnimation.state != PRE_DIGEST_STATE)) { + skipAnimations = !areAnimationsAllowed(element, parent, event); + } + + if (skipAnimations) { + close(); + return runner; + } + + if (isStructural) { + closeChildAnimations(element); + } + + var newAnimation = { + structural: isStructural, + element: element, + event: event, + options: options, + runner: runner + }; + + if (hasExistingAnimation) { + var skipAnimationFlag = isAllowed('skip', element, newAnimation, existingAnimation); + if (skipAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + close(); + return runner; + } else { + mergeAnimationOptions(element, existingAnimation.options, options); + return existingAnimation.runner; + } + } + + var cancelAnimationFlag = isAllowed('cancel', element, newAnimation, existingAnimation); + if (cancelAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + existingAnimation.runner.end(); + } else { + mergeAnimationOptions(element, newAnimation.options, existingAnimation.options); + } + } else { + // a joined animation means that this animation will take over the existing one + // so an example would involve a leave animation taking over an enter. Then when + // the postDigest kicks in the enter will be ignored. + var joinAnimationFlag = isAllowed('join', element, newAnimation, existingAnimation); + if (joinAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + normalizeAnimationOptions(element, options); + } else { + event = newAnimation.event = existingAnimation.event; + options = mergeAnimationOptions(element, existingAnimation.options, newAnimation.options); + return runner; + } + } + } + } else { + // normalization in this case means that it removes redundant CSS classes that + // already exist (addClass) or do not exist (removeClass) on the element + normalizeAnimationOptions(element, options); + } + + // when the options are merged and cleaned up we may end up not having to do + // an animation at all, therefore we should check this before issuing a post + // digest callback. Structural animations will always run no matter what. + var isValidAnimation = newAnimation.structural; + if (!isValidAnimation) { + // animate (from/to) can be quickly checked first, otherwise we check if any classes are present + isValidAnimation = (newAnimation.event === 'animate' && Object.keys(newAnimation.options.to || {}).length > 0) + || hasAnimationClasses(newAnimation.options); + } + + if (!isValidAnimation) { + close(); + return runner; + } + + closeParentClassBasedAnimations(parent); + + // the counter keeps track of cancelled animations + var counter = (existingAnimation.counter || 0) + 1; + newAnimation.counter = counter; + + markElementAnimationState(element, PRE_DIGEST_STATE, newAnimation); + + $rootScope.$$postDigest(function() { + var animationDetails = activeAnimationsLookup.get(node); + var animationCancelled = !animationDetails; + animationDetails = animationDetails || {}; + + // if addClass/removeClass is called before something like enter then the + // registered parent element may not be present. The code below will ensure + // that a final value for parent element is obtained + var parentElement = element.parent() || []; + + // animate/structural/class-based animations all have requirements. Otherwise there + // is no point in performing an animation. The parent node must also be set. + var isValidAnimation = parentElement.length > 0 + && (animationDetails.event === 'animate' + || animationDetails.structural + || hasAnimationClasses(animationDetails.options)); + + // this means that the previous animation was cancelled + // even if the follow-up animation is the same event + if (animationCancelled || animationDetails.counter !== counter || !isValidAnimation) { + // if another animation did not take over then we need + // to make sure that the domOperation and options are + // handled accordingly + if (animationCancelled) { + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + } + + // if the event changed from something like enter to leave then we do + // it, otherwise if it's the same then the end result will be the same too + if (animationCancelled || (isStructural && animationDetails.event !== event)) { + options.domOperation(); + } + + return; + } + + // this combined multiple class to addClass / removeClass into a setClass event + // so long as a structural event did not take over the animation + event = !animationDetails.structural && hasAnimationClasses(animationDetails.options, true) + ? 'setClass' + : animationDetails.event; + + closeParentClassBasedAnimations(parentElement); + + markElementAnimationState(element, RUNNING_STATE); + var realRunner = $$animation(element, event, animationDetails.options); + realRunner.done(function(status) { + close(!status); + var animationDetails = activeAnimationsLookup.get(node); + if (animationDetails && animationDetails.counter === counter) { + clearElementAnimationState(element); + } + notifyProgress(runner, event, 'close', {}); + }); + + // this will update the runner's flow-control events based on + // the `realRunner` object. + runner.setHost(realRunner); + notifyProgress(runner, event, 'start', {}); + }); + + return runner; + + function notifyProgress(runner, event, phase, data) { + triggerCallback(event, element, phase, data); + runner.progress(event, phase, data); + } + + function close(reject) { // jshint ignore:line + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + options.domOperation(); + runner.complete(!reject); + } + } + + function closeChildAnimations(element) { + var node = element[0]; + var children = node.querySelectorAll('[' + NG_ANIMATE_ATTR_NAME + ']'); + forEach(children, function(child) { + var state = parseInt(child.getAttribute(NG_ANIMATE_ATTR_NAME)); + var animationDetails = activeAnimationsLookup.get(child); + switch (state) { + case RUNNING_STATE: + animationDetails.runner.end(); + /* falls through */ + case PRE_DIGEST_STATE: + if (animationDetails) { + activeAnimationsLookup.remove(child); + } + break; + } + }); + } + + function clearElementAnimationState(element) { + element = element.length ? element[0] : element; + element.removeAttribute(NG_ANIMATE_ATTR_NAME); + activeAnimationsLookup.remove(element); + } + + function isMatchingElement(a,b) { + a = a.length ? a[0] : a; + b = b.length ? b[0] : b; + return a === b; + } + + function closeParentClassBasedAnimations(startingElement) { + var parentNode = startingElement[0]; + do { + if (!parentNode || parentNode.nodeType !== ELEMENT_NODE) break; + + var animationDetails = activeAnimationsLookup.get(parentNode); + if (animationDetails) { + examineParentAnimation(parentNode, animationDetails); + } + + parentNode = parentNode.parentNode; + } while (true); + + // since animations are detected from CSS classes, we need to flush all parent + // class-based animations so that the parent classes are all present for child + // animations to properly function (otherwise any CSS selectors may not work) + function examineParentAnimation(node, animationDetails) { + // enter/leave/move always have priority + if (animationDetails.structural) return; + + if (animationDetails.state === RUNNING_STATE) { + animationDetails.runner.end(); + } + clearElementAnimationState(node); + } + } + + function areAnimationsAllowed(element, parent, event) { + var bodyElementDetected = false; + var rootElementDetected = false; + var parentAnimationDetected = false; + var animateChildren; + + while (parent && parent.length) { + var parentNode = parent[0]; + if (parentNode.nodeType !== ELEMENT_NODE) { + // no point in inspecting the #document element + break; + } + + var details = activeAnimationsLookup.get(parentNode) || {}; + // either an enter, leave or move animation will commence + // therefore we can't allow any animations to take place + // but if a parent animation is class-based then that's ok + if (!parentAnimationDetected) { + parentAnimationDetected = details.structural || disabledElementsLookup.get(parentNode); + } + + if (isUndefined(animateChildren) || animateChildren === true) { + var value = parent.data(NG_ANIMATE_CHILDREN_DATA); + if (isDefined(value)) { + animateChildren = value; + } + } + + // there is no need to continue traversing at this point + if (parentAnimationDetected && animateChildren === false) break; + + if (!rootElementDetected) { + // angular doesn't want to attempt to animate elements outside of the application + // therefore we need to ensure that the rootElement is an ancestor of the current element + rootElementDetected = isMatchingElement(parent, $rootElement); + } + + if (!bodyElementDetected) { + // we also need to ensure that the element is or will be apart of the body element + // otherwise it is pointless to even issue an animation to be rendered + bodyElementDetected = isMatchingElement(parent, bodyElement); + } + + parent = parent.parent(); + } + + var allowAnimation = !parentAnimationDetected || animateChildren; + return allowAnimation && rootElementDetected && bodyElementDetected; + } + + function markElementAnimationState(element, state, details) { + details = details || {}; + details.state = state; + + element = element.length ? element[0] : element; + element.setAttribute(NG_ANIMATE_ATTR_NAME, state); + + var oldValue = activeAnimationsLookup.get(element); + var newValue = oldValue + ? extend(oldValue, details) + : details; + activeAnimationsLookup.put(element, newValue); + } + }]; +}]; diff --git a/src/ngAnimate/animateRunner.js b/src/ngAnimate/animateRunner.js new file mode 100644 index 000000000000..65b1e8d48030 --- /dev/null +++ b/src/ngAnimate/animateRunner.js @@ -0,0 +1,151 @@ +'use strict'; + +var $$rAFMutexFactory = ['$$rAF', function($$rAF) { + return function() { + var passed = false; + $$rAF(function() { + passed = true; + }); + return function(fn) { + passed ? fn() : $$rAF(fn); + }; + }; +}]; + +var $$AnimateRunnerFactory = ['$q', '$$rAFMutex', function($q, $$rAFMutex) { + var INITIAL_STATE = 0; + var DONE_PENDING_STATE = 1; + var DONE_COMPLETE_STATE = 2; + + AnimateRunner.chain = function(chain, callback) { + var index = 0; + + next(); + function next() { + if (index === chain.length) { + callback(true); + return; + } + + chain[index](function(response) { + if (response === false) { + callback(false); + return; + } + index++; + next(); + }); + } + }; + + AnimateRunner.all = function(runners, callback) { + var count = 0; + var status = true; + forEach(runners, function(runner) { + runner.done(onProgress); + }); + + function onProgress(response) { + status = status && response; + if (++count === runners.length) { + callback(status); + } + } + }; + + function AnimateRunner(host) { + this.setHost(host); + + this._doneCallbacks = []; + this._runInAnimationFrame = $$rAFMutex(); + this._state = 0; + } + + AnimateRunner.prototype = { + setHost: function(host) { + this.host = host || {}; + }, + + done: function(fn) { + if (this._state === DONE_COMPLETE_STATE) { + fn(); + } else { + this._doneCallbacks.push(fn); + } + }, + + progress: noop, + + getPromise: function() { + if (!this.promise) { + var self = this; + this.promise = $q(function(resolve, reject) { + self.done(function(status) { + status === false ? reject() : resolve(); + }); + }); + } + return this.promise; + }, + + then: function(resolveHandler, rejectHandler) { + return this.getPromise().then(resolveHandler, rejectHandler); + }, + + 'catch': function(handler) { + return this.getPromise()['catch'](handler); + }, + + 'finally': function(handler) { + return this.getPromise()['finally'](handler); + }, + + pause: function() { + if (this.host.pause) { + this.host.pause(); + } + }, + + resume: function() { + if (this.host.resume) { + this.host.resume(); + } + }, + + end: function() { + if (this.host.end) { + this.host.end(); + } + this._resolve(true); + }, + + cancel: function() { + if (this.host.cancel) { + this.host.cancel(); + } + this._resolve(false); + }, + + complete: function(response) { + var self = this; + if (self._state === INITIAL_STATE) { + self._state = DONE_PENDING_STATE; + self._runInAnimationFrame(function() { + self._resolve(response); + }); + } + }, + + _resolve: function(response) { + if (this._state !== DONE_COMPLETE_STATE) { + forEach(this._doneCallbacks, function(fn) { + fn(response); + }); + this._doneCallbacks.length = 0; + this._state = DONE_COMPLETE_STATE; + } + } + }; + + return AnimateRunner; +}]; diff --git a/src/ngAnimate/animation.js b/src/ngAnimate/animation.js new file mode 100644 index 000000000000..0c52760d56bd --- /dev/null +++ b/src/ngAnimate/animation.js @@ -0,0 +1,288 @@ +'use strict'; + +var $$AnimationProvider = ['$animateProvider', function($animateProvider) { + var NG_ANIMATE_CLASSNAME = 'ng-animate'; + var NG_ANIMATE_REF_ATTR = 'ng-animate-ref'; + + var drivers = this.drivers = []; + + var RUNNER_STORAGE_KEY = '$$animationRunner'; + + function setRunner(element, runner) { + element.data(RUNNER_STORAGE_KEY, runner); + } + + function removeRunner(element) { + element.removeData(RUNNER_STORAGE_KEY); + } + + function getRunner(element) { + return element.data(RUNNER_STORAGE_KEY); + } + + this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', + function($$jqLite, $rootScope, $injector, $$AnimateRunner) { + + var animationQueue = []; + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + // TODO(matsko): document the signature in a better way + return function(element, event, options) { + options = prepareAnimationOptions(options); + var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0; + + // there is no animation at the current moment, however + // these runner methods will get later updated with the + // methods leading into the driver's end/cancel methods + // for now they just stop the animation from starting + var runner = new $$AnimateRunner({ + end: function() { close(); }, + cancel: function() { close(true); } + }); + + if (!drivers.length) { + close(); + return runner; + } + + setRunner(element, runner); + + var classes = mergeClasses(element.attr('class'), mergeClasses(options.addClass, options.removeClass)); + var tempClasses = options.tempClasses; + if (tempClasses) { + classes += ' ' + tempClasses; + options.tempClasses = null; + } + + animationQueue.push({ + // this data is used by the postDigest code and passed into + // the driver step function + element: element, + classes: classes, + event: event, + structural: isStructural, + options: options, + start: start, + close: close + }); + + element.on('$destroy', handleDestroyedElement); + + // we only want there to be one function called within the post digest + // block. This way we can group animations for all the animations that + // were apart of the same postDigest flush call. + if (animationQueue.length > 1) return runner; + + $rootScope.$$postDigest(function() { + var animations = []; + forEach(animationQueue, function(entry) { + // the element was destroyed early on which removed the runner + // form its storage. This means we can't animate this element + // at all and it already has been closed due to destruction. + if (getRunner(entry.element)) { + animations.push(entry); + } + }); + + // now any future animations will be in another postDigest + animationQueue.length = 0; + + forEach(groupAnimations(animations), function(animationEntry) { + var startFn = animationEntry.start; + var closeFn = animationEntry.close; + var operation = invokeFirstDriver(animationEntry); + var startAnimation = operation && operation.start; /// TODO(matsko): only recognize operation.start() + if (!startAnimation) { + closeFn(); + } else { + startFn(); + var animationRunner = startAnimation(); + animationRunner.done(function(status) { + closeFn(!status); + }); + updateAnimationRunners(animationEntry, animationRunner); + } + }); + }); + + return runner; + + // TODO(matsko): change to reference nodes + function getAnchorNodes(node) { + var SELECTOR = '[' + NG_ANIMATE_REF_ATTR + ']'; + var items = node.hasAttribute(NG_ANIMATE_REF_ATTR) + ? [node] + : node.querySelectorAll(SELECTOR); + var anchors = []; + forEach(items, function(node) { + var attr = node.getAttribute(NG_ANIMATE_REF_ATTR); + if (attr && attr.length) { + anchors.push(node); + } + }); + return anchors; + } + + function groupAnimations(animations) { + var preparedAnimations = []; + var refLookup = {}; + forEach(animations, function(animation, index) { + var element = animation.element; + var node = element[0]; + var event = animation.event; + var enterOrMove = ['enter', 'move'].indexOf(event) >= 0; + var anchorNodes = animation.structural ? getAnchorNodes(node) : []; + + if (anchorNodes.length) { + var direction = enterOrMove ? 'to' : 'from'; + + forEach(anchorNodes, function(anchor) { + var key = anchor.getAttribute(NG_ANIMATE_REF_ATTR); + refLookup[key] = refLookup[key] || {}; + refLookup[key][direction] = { + animationID: index, + element: jqLite(anchor) + }; + }); + } else { + preparedAnimations.push(animation); + } + }); + + var usedIndicesLookup = {}; + var anchorGroups = {}; + forEach(refLookup, function(operations, key) { + var from = operations.from; + var to = operations.to; + + if (!from || !to) { + // only one of these is set therefore we can't have an + // anchor animation since all three pieces are required + var index = from ? from.animationID : to.animationID; + var indexKey = index.toString(); + if (!usedIndicesLookup[indexKey]) { + usedIndicesLookup[indexKey] = true; + preparedAnimations.push(animations[index]); + } + return; + } + + var fromAnimation = animations[from.animationID]; + var toAnimation = animations[to.animationID]; + var lookupKey = from.animationID.toString(); + if (!anchorGroups[lookupKey]) { + var group = anchorGroups[lookupKey] = { + // TODO(matsko): double-check this code + start: function() { + fromAnimation.start(); + toAnimation.start(); + }, + close: function() { + fromAnimation.close(); + toAnimation.close(); + }, + classes: cssClassesIntersection(fromAnimation.classes, toAnimation.classes), + from: fromAnimation, + to: toAnimation, + anchors: [] // TODO(matsko): change to reference nodes + }; + + // the anchor animations require that the from and to elements both have at least + // one shared CSS class which effictively marries the two elements together to use + // the same animation driver and to properly sequence the anchor animation. + if (group.classes.length) { + preparedAnimations.push(group); + } else { + preparedAnimations.push(fromAnimation); + preparedAnimations.push(toAnimation); + } + } + + anchorGroups[lookupKey].anchors.push({ + 'out': from.element, 'in': to.element + }); + }); + + return preparedAnimations; + } + + function cssClassesIntersection(a,b) { + a = a.split(' '); + b = b.split(' '); + var matches = []; + + for (var i = 0; i < a.length; i++) { + var aa = a[i]; + if (aa.substring(0,3) === 'ng-') continue; + + for (var j = 0; j < b.length; j++) { + if (aa === b[j]) { + matches.push(aa); + break; + } + } + } + + return matches.join(' '); + } + + function invokeFirstDriver(animationDetails) { + // we loop in reverse order since the more general drivers (like CSS and JS) + // may attempt more elements, but custom drivers are more particular + for (var i = drivers.length - 1; i >= 0; i--) { + var driverName = drivers[i]; + if (!$injector.has(driverName)) continue; // TODO(matsko): remove this check + + var factory = $injector.get(driverName); + var driver = factory(animationDetails); + if (driver) { + return driver; + } + } + } + + function start() { + element.addClass(NG_ANIMATE_CLASSNAME); + if (tempClasses) { + $$jqLite.addClass(element, tempClasses); + } + } + + function updateAnimationRunners(animation, newRunner) { + if (animation.from && animation.to) { + update(animation.from.element); + update(animation.to.element); + } else { + update(animation.element); + } + + function update(element) { + getRunner(element).setHost(newRunner); + } + } + + function handleDestroyedElement() { + var runner = getRunner(element); + if (runner && (event !== 'leave' || !options.$$domOperationFired)) { + runner.end(); + } + } + + function close(rejected) { // jshint ignore:line + element.off('$destroy', handleDestroyedElement); + removeRunner(element); + + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + options.domOperation(); + + if (tempClasses) { + $$jqLite.removeClass(element, tempClasses); + } + + element.removeClass(NG_ANIMATE_CLASSNAME); + runner.complete(!rejected); + } + }; + }]; +}]; diff --git a/src/ngAnimate/module.js b/src/ngAnimate/module.js new file mode 100644 index 000000000000..f5e90a9fd7b2 --- /dev/null +++ b/src/ngAnimate/module.js @@ -0,0 +1,508 @@ +'use strict'; + +/* global angularAnimateModule: true, + + $$rAFMutexFactory, + $$AnimateChildrenDirective, + $$AnimateRunnerFactory, + $$AnimateQueueProvider, + $$AnimationProvider, + $AnimateCssProvider, + $$AnimateCssDriverProvider, + $$AnimateJsProvider, + $$AnimateJsDriverProvider, +*/ + +/** + * @ngdoc module + * @name ngAnimate + * @description + * + * The `ngAnimate` module provides support for CSS-based animations (keyframes and transitions) as well as JavaScript-based animations via + * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` then the animation hooks are enabled for an Angular app. + * + *
+ * + * # Usage + * Simply put, there are two ways to make use of animations when ngAnimate is used: by using **CSS** and **JavaScript**. The former works purely based + * using CSS (by using matching CSS selectors/styles) and the latter triggers animations that are registered via `module.animation()`. For + * both CSS and JS animations the sole requirement is to have a matching `CSS class` that exists both in the registered animation and within + * the HTML element that the animation will be triggered on. + * + * ## Directive Support + * The following directives are "animation aware": + * + * | Directive | Supported Animations | + * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------| + * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move | + * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave | + * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave | + * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave | + * | {@link ng.directive:ngIf#animations ngIf} | enter and leave | + * | {@link ng.directive:ngClass#animations ngClass} | add and remove (the CSS class(es) present) | + * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide} | add and remove (the ng-hide class value) | + * | {@link ng.directive:form#animation-hooks form} & {@link ng.directive:ngModel#animation-hooks ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) | + * | {@link module:ngMessages#animations ngMessages} | add and remove (ng-active & ng-inactive) | + * | {@link module:ngMessages#animations ngMessage} | enter and leave | + * + * (More information can be found by visiting each the documentation associated with each directive.) + * + * ## CSS-based Animations + * + * CSS-based animations with ngAnimate are unique since they require no JavaScript code at all. By using a CSS class that we reference between our HTML + * and CSS code we can create an animation that will be picked up by Angular when an the underlying directive performs an operation. + * + * The example below shows how an `enter` animation can be made possible on a element using `ng-if`: + * + * ```html + *
+ * Fade me in out + *
+ * + * + * ``` + * + * Notice the CSS class **fade**? We can now create the CSS transition code that references this class: + * + * ```css + * /* The starting CSS styles for the enter animation */ + * .fade.ng-enter { + * transition:0.5s linear all; + * opacity:0; + * } + * + * /* The starting CSS styles for the enter animation */ + * .fade.ng-enter.ng-enter-active { + * opacity:1; + * } + * ``` + * + * The key thing to remember here is that, depending on the animation event (which each of the directives above trigger depending on what's going on) two + * generated CSS classes will be applied to the element; in the example above we have `.ng-enter` and `.ng-enter-active`. For CSS transitions, the transition + * code **must** be defined within the starting CSS class (in this case `.ng-enter`). The destination class is what the transition will animate towards. + * + * If for example we wanted to create animations for `leave` and `move` (ngRepeat triggers move) then we can do so using the same CSS naming conventions: + * + * ```css + * /* now the element will fade out before it is removed from the DOM */ + * .fade.ng-leave { + * transition:0.5s linear all; + * opacity:1; + * } + * .fade.ng-leave.ng-leave-active { + * opacity:0; + * } + * ``` + * + * We can also make use of **CSS Keyframes** by referencing the keyframe animation within the starting CSS class: + * + * ```css + * /* there is no need to define anything inside of the destination + * CSS class since the keyframe will take charge of the animation */ + * .fade.ng-leave { + * animation: my_fade_animation 0.5s linear; + * -webkit-animation: my_fade_animation 0.5s linear; + * } + * + * @keyframes my_fade_animation { + * from { opacity:1; } + * to { opacity:0; } + * } + * + * @-webkit-keyframes my_fade_animation { + * from { opacity:1; } + * to { opacity:0; } + * } + * ``` + * + * Feel free also mix transitions and keyframes together as well as any other CSS classes on the same element. + * + * ### CSS Class-based Animations + * + * Class-based animations (animations that are triggered via `ngClass`, `ngShow`, `ngHide` and some other directives) have a slightly different + * naming convention. Class-based animations are basic enough that a standard transition or keyframe can be referenced on the class being added + * and removed. + * + * For example if we wanted to do a CSS animation for `ngHide` then we place an animation on the `.ng-hide` CSS class: + * + * ```html + *
+ * Show and hide me + *
+ * + * + * + * ``` + * + * All that is going on here with ngShow/ngHide behind the scenes is the `.ng-hide` class is added/removed (when the hidden state is valid). Since + * ngShow and ngHide are animation aware then we can match up a transition and ngAnimate handles the rest. + * + * In addition the addition and removal of the CSS class, ngAnimate also provides two helper methods that we can use to further decorate the animation + * with CSS styles. + * + * ```html + *
+ * Highlight this box + *
+ * + * + * + * ``` + * + * We can also make use of CSS keyframes by placing them within the CSS classes. + * + * + * ### CSS Staggering Animations + * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a + * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be + * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for + * the animation. The style property expected within the stagger class can either be a **transition-delay** or an + * **animation-delay** property (or both if your animation contains both transitions and keyframe animations). + * + * ```css + * .my-animation.ng-enter { + * /* standard transition code */ + * transition: 1s linear all; + * opacity:0; + * } + * .my-animation.ng-enter-stagger { + * /* this will have a 100ms delay between each successive leave animation */ + * transition-delay: 0.1s; + * + * /* in case the stagger doesn't work then the duration value + * must be set to 0 to avoid an accidental CSS inheritance */ + * transition-duration: 0s; + * } + * .my-animation.ng-enter.ng-enter-active { + * /* standard transition styles */ + * opacity:1; + * } + * ``` + * + * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations + * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this + * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation + * will also be reset if one or more animation frames have passed since the multiple calls to `$animate` were fired. + * + * The following code will issue the **ng-leave-stagger** event on the element provided: + * + * ```js + * var kids = parent.children(); + * + * $animate.leave(kids[0]); //stagger index=0 + * $animate.leave(kids[1]); //stagger index=1 + * $animate.leave(kids[2]); //stagger index=2 + * $animate.leave(kids[3]); //stagger index=3 + * $animate.leave(kids[4]); //stagger index=4 + * + * window.requestAnimationFrame(function() { + * //stagger has reset itself + * $animate.leave(kids[5]); //stagger index=0 + * $animate.leave(kids[6]); //stagger index=1 + * + * $scope.$digest(); + * }); + * ``` + * + * Stagger animations are currently only supported within CSS-defined animations. + * + * ## JavaScript-based Animations + * + * ngAnimate also allows for animations to be consumed by JavaScript code. The approach is similar to CSS-based animations (where there is a shared + * CSS class that is referenced in our HTML code) but in addition we need to register the JavaScript animation on the module. By making use of the + * `module.animation()` module function we can register the ainmation. + * + * Let's see an example of a enter/leave animation using `ngRepeat`: + * + * ```html + *
+ * {{ item }} + *
+ * ``` + * + * See the **slide** CSS class? Let's use that class to define an animation that we'll structure in our module code by using `module.animation`: + * + * ```js + * myModule.animation('.slide', [function() { + * return { + * // make note that other events (like addClass/removeClass) + * // have different function input parameters + * enter: function(element, doneFn) { + * jQuery(element).fadeIn(1000, doneFn); + * + * // remember to call doneFn so that angular + * // knows that the animation has concluded + * }, + * + * move: function(element, doneFn) { + * jQuery(element).fadeIn(1000, doneFn); + * }, + * + * leave: function(element, doneFn) { + * jQuery(element).fadeOut(1000, doneFn); + * } + * } + * }] + * ``` + * + * The nice thing about JS-based animations is that we can inject other services and make use of advanced animation libraries such as + * greensock.js and velocity.js. + * + * If our animation code class-based (meaning that something like `ngClass`, `ngHide` and `ngShow` triggers it) then we can still define + * our animations inside of the same registered animation, however, the function input arguments are a bit different: + * + * ```html + *
+ * this box is moody + *
+ * + * + * + * ``` + * + * ```js + * myModule.animation('.colorful', [function() { + * return { + * addClass: function(element, className, doneFn) { + * // do some cool animation and call the doneFn + * }, + * removeClass: function(element, className, doneFn) { + * // do some cool animation and call the doneFn + * }, + * setClass: function(element, addedClass, removedClass, doneFn) { + * // do some cool animation and call the doneFn + * } + * } + * }] + * ``` + * + * ## CSS + JS Animations Together + * + * AngularJS 1.4 and higher has taken steps to make the amalgamation of CSS and JS animations more flexible. However, unlike earlier versions of Angular, + * defining CSS and JS animations to work off of the same CSS class will not work anymore. Therefore example below will only result in **JS animations taking + * charge of the animation**: + * + * ```html + *
+ * Slide in and out + *
+ * ``` + * + * ```js + * myModule.animation('.slide', [function() { + * return { + * enter: function(element, doneFn) { + * jQuery(element).slideIn(1000, doneFn); + * } + * } + * }] + * ``` + * + * ```css + * .slide.ng-enter { + * transition:0.5s linear all; + * transform:translateY(-100px); + * } + * .slide.ng-enter.ng-enter-active { + * transform:translateY(0); + * } + * ``` + * + * Does this mean that CSS and JS animations cannot be used together? Do JS-based animations always have higher priority? We can suppliment for the + * lack of CSS animations by making use of the `$animateCss` service to trigger our own tweaked-out, CSS-based animations directly from + * our own JS-based animation code: + * + * ```js + * myModule.animation('.slide', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var animation = $animateCss(element, { + * event: 'enter' + * }); + * + * if (animation) { + * // this will trigger `.slide.ng-enter` and `.slide.ng-enter-active`. + * var runner = animation.start(); + * runner.done(doneFn); + * } else { //no CSS animation was detected + * doneFn(); + * } + * } + * } + * }] + * ``` + * + * The nice thing here is that we can save bandwidth by sticking to our CSS-based animation code and we don't need to rely on a 3rd-party animation framework. + * + * The `$animateCss` service is very powerful since we can feed in all kinds of extra properties that will be evaluated and fed into a CSS transition or + * keyframe animation. For example if we wanted to animate the height of an element while adding and removing classes then we can do so by providing that + * data into `$animateCss` directly: + * + * ```js + * myModule.animation('.slide', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var animation = $animateCss(element, { + * event: 'enter', + * addClass: 'maroon-setting', + * from: { height:0 }, + * to: { height: 200 } + * }); + * + * if (animation) { + * animation.start().done(doneFn); + * } else { + * doneFn(); + * } + * } + * } + * }] + * ``` + * + * Now we can fill in the rest via our transition CSS code: + * + * ```css + * /* the transition tells ngAnimate to make the animation happen */ + * .slide.ng-enter { transition:0.5s linear all; } + * + * /* this extra CSS class will be absorbed into the transition + * since the $animateCss code is adding the class */ + * .maroon-setting { background:red; } + * ``` + * + * And `$animateCss` will figure out the rest. Just make sure to have the `done()` callback fire the `doneFn` function to signal when the animation is over. + * + * To learn more about what's possible be sure to visit the {@link ngAnimate.$animateCss $animateCss service}. + * + * + * ## Using $animate in your directive code + * + * So far we've explored how to feed in animations into an Angular application, but how do we trigger animations within our own directives in our application? + * By injecting the `$animate` service into our directive code, we can trigger structural and class-based hooks which can then be consumed by animations. Let's + * imagine we have a greeting box that shows and hides itself when the data changes + * + * ```html + * Hi there + * ``` + * + * ```js + * ngModule.directive('greetingBox', ['$animate', function($animate) { + * return function(scope, element, attrs) { + * attrs.$observe('active', function(value) { + * value ? $animate.addClass(element, 'on') ? $animate.removeClass(element, 'on'); + * }); + * }); + * }]); + * ``` + * + * Now the `on` CSS class is added and removed on the greeting box component. Now if we add a CSS class on top of the greeting box element + * in our HTML code then we can trigger a CSS or JS animation to happen. + * + * ```css + * /* normally we would create a CSS class to reference on the element */ + * [greeting-box].on { transition:0.5s linear all; background:green; color:white; } + * ``` + * + * The `$animate` service contains a variety of other methods like `enter`, `leave`, `animate` and `setClass`. To learn more about what's + * possible be sure to visit the {@link ng.$animate $animate service API page}. + * + * + * ### Preventing Collisions With Third Party Libraries + * + * Some third-party frameworks place animation duration defaults across many element or className + * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which + * is expecting actual animations on these elements and has to wait for their completion. + * + * You can prevent this unwanted behavior by using a prefix on all your animation classes: + * + * ```css + * /* prefixed with animate- */ + * .animate-fade-add.animate-fade-add-active { + * transition:1s linear all; + * opacity:0; + * } + * ``` + * + * You then configure `$animate` to enforce this prefix: + * + * ```js + * $animateProvider.classNameFilter(/animate-/); + * ``` + * + * This also may provide your application with a speed boost since only specific elements containing CSS class prefix + * will be evaluated for animation when any DOM changes occur in the application. + * + * ## Callbacks and Promises + * + * When `$animate` is called it returns a promise that can be used to capture when the animation has ended. Therefore if we were to trigger + * an animation (within our directive code) then we can continue performing directive and scope related activities after the animation has + * ended by chaining onto the returned promise that animation method returns. + * + * ```js + * // somewhere within the depths of the directive + * $animate.enter(element, parent).then(function() { + * //the animation has completed + * }); + * ``` + * + * (Note that earlier versions of Angular prior to v1.4 required the promise code to be wrapped using `$scope.$apply(...)`. This is not the case + * anymore.) + * + * In addition to the animation promise, we can also make use of animation-related callbacks within our directives and controller code by registering + * an event listener using the `$animate` service. Let's say for example that an animation was triggered on our `ng-view` element and we wanted our + * routing controller to hook into that: + * + * ```js + * ngModule.controller('HomePageController', ['$animate', function($animate) { + * $animate.on('enter', '[ng-view]', function(element) { + * // the animation for this route has completed + * }]); + * }]) + * ``` + * + * (Note that you will need to trigger a digest within the callback to get angular to notice any scope-related changes.) + */ + +/** + * @ngdoc service + * @name $animate + * @kind object + * + * @description + * The ngAnimate `$animate` service documentation is the same for the core `$animate` service. + * + * Click here {@link ng.$animate $animate to learn more about animations with `$animate`}. + */ +angular.module('ngAnimate', []) + .directive('ngAnimateChildren', $$AnimateChildrenDirective) + + .factory('$$rAFMutex', $$rAFMutexFactory) + + .factory('$$AnimateRunner', $$AnimateRunnerFactory) + + .provider('$$animateQueue', $$AnimateQueueProvider) + .provider('$$animation', $$AnimationProvider) + + .provider('$animateCss', $AnimateCssProvider) + .provider('$$animateCssDriver', $$AnimateCssDriverProvider) + + .provider('$$animateJs', $$AnimateJsProvider) + .provider('$$animateJsDriver', $$AnimateJsDriverProvider); diff --git a/src/ngAnimate/shared.js b/src/ngAnimate/shared.js new file mode 100644 index 000000000000..985d4d170109 --- /dev/null +++ b/src/ngAnimate/shared.js @@ -0,0 +1,230 @@ +'use strict'; + +/* jshint ignore:start */ +var noop = angular.noop; +var extend = angular.extend; +var jqLite = angular.element; +var forEach = angular.forEach; +var isArray = angular.isArray; +var isString = angular.isString; +var isObject = angular.isObject; +var isUndefined = angular.isUndefined; +var isDefined = angular.isDefined; +var isFunction = angular.isFunction; +var isElement = angular.isElement; + +var ELEMENT_NODE = 1; +var COMMENT_NODE = 8; + +var NG_ANIMATE_CHILDREN_DATA = '$$ngAnimateChildren'; + +var isPromiseLike = function(p) { + return p && p.then ? true : false; +} + +function mergeClasses(a,b) { + if (!a && !b) return ''; + if (!a) return b; + if (!b) return a; + if (isArray(a)) a = a.join(' '); + if (isArray(b)) b = b.join(' '); + return a + ' ' + b; +} + +function packageStyles(options) { + var styles = {}; + if (options && (options.to || options.from)) { + styles.to = options.to; + styles.from = options.from; + } + return styles; +} + +function pendClasses(classes, fix, isPrefix) { + var className = ''; + classes = isArray(classes) + ? classes + : classes && isString(classes) && classes.length + ? classes.split(/\s+/) + : []; + forEach(classes, function(klass, i) { + if (klass && klass.length > 0) { + className += (i > 0) ? ' ' : ''; + className += isPrefix ? fix + klass + : klass + fix; + } + }); + return className; +} + +function removeFromArray(arr, val) { + var index = arr.indexOf(val); + if (val >= 0) { + arr.splice(index, 1); + } +} + +function stripCommentsFromElement(element) { + if (element.nodeType === ELEMENT_NODE) { + return jqLite(element); + } + if (element.length === 0) return []; + + // there is no point of stripping anything if the element + // is the only element within the jqLite wrapper. + // (it's important that we retain the element instance.) + if (element.length === 1) { + return element[0].nodeType === ELEMENT_NODE && element; + } else { + return jqLite(extractElementNode(element)); + } +} + +function extractElementNode(element) { + if (!element[0]) return element; + for (var i = 0; i < element.length; i++) { + var elm = element[i]; + if (elm.nodeType == ELEMENT_NODE) { + return elm; + } + } +} + +function $$addClass($$jqLite, element, className) { + forEach(element, function(elm) { + $$jqLite.addClass(elm, className); + }); +} + +function $$removeClass($$jqLite, element, className) { + forEach(element, function(elm) { + $$jqLite.removeClass(elm, className); + }); +} + +function applyAnimationClassesFactory($$jqLite) { + return function(element, options) { + if (options.addClass) { + $$addClass($$jqLite, element, options.addClass); + options.addClass = null; + } + if (options.removeClass) { + $$removeClass($$jqLite, element, options.removeClass); + element.removeClass(options.removeClass); + options.removeClass = null; + } + } +} + +function prepareAnimationOptions(options) { + options = options || {}; + if (!options.$$prepared) { + var domOperation = options.domOperation || noop; + options.domOperation = function() { + options.$$domOperationFired = true; + domOperation(); + domOperation = noop; + }; + options.$$prepared = true; + } + return options; +} + +function applyAnimationStyles(element, options) { + applyAnimationFromStyles(element, options); + applyAnimationToStyles(element, options); +} + +function applyAnimationFromStyles(element, options) { + if (options.from) { + element.css(options.from); + options.from = null; + } +} + +function applyAnimationToStyles(element, options) { + if (options.to) { + element.css(options.to); + options.to = null; + } +} + +function mergeAnimationOptions(element, target, newOptions) { + var toAdd = (target.addClass || '') + ' ' + (newOptions.addClass || ''); + var toRemove = (target.removeClass || '') + ' ' + (newOptions.removeClass || ''); + var classes = resolveElementClasses(element.attr('class'), toAdd, toRemove); + + extend(target, newOptions); + + if (classes.addClass) { + target.addClass = classes.addClass; + } else { + target.addClass = null; + } + + if (classes.removeClass) { + target.removeClass = classes.removeClass; + } else { + target.removeClass = null; + } + + return target; +} + +function resolveElementClasses(existing, toAdd, toRemove) { + var ADD_CLASS = 1; + var REMOVE_CLASS = -1; + + var flags = {}; + existing = splitClassesToLookup(existing); + + toAdd = splitClassesToLookup(toAdd); + forEach(toAdd, function(value, key) { + flags[key] = ADD_CLASS; + }); + + toRemove = splitClassesToLookup(toRemove); + forEach(toRemove, function(value, key) { + flags[key] = flags[key] === ADD_CLASS ? null : REMOVE_CLASS; + }); + + var classes = { + addClass: '', + removeClass: '' + }; + + forEach(flags, function(val, klass) { + var prop, allow; + if (val === ADD_CLASS) { + prop = 'addClass'; + allow = !existing[klass]; + } else if (val === REMOVE_CLASS) { + prop = 'removeClass'; + allow = existing[klass]; + } + if (allow) { + if (classes[prop].length) { + classes[prop] += ' '; + } + classes[prop] += klass; + } + }); + + function splitClassesToLookup(classes) { + if (isString(classes)) { + classes = classes.split(' '); + } + + var obj = {}; + forEach(classes, function(klass) { + // sometimes the split leaves empty string values + // incase extra spaces were applied to the options + if (klass.length) { + obj[klass] = true; + } + }); + return obj; + } + + return classes; +} diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index 6208a9fdb4cc..dd11e45701ab 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -764,13 +764,14 @@ angular.mock.animate = angular.module('ngAnimateMock', ['ng']) }; }); - $provide.decorator('$animate', ['$delegate', '$$asyncCallback', '$timeout', '$browser', - function($delegate, $$asyncCallback, $timeout, $browser) { + $provide.decorator('$animate', ['$delegate', '$$asyncCallback', '$timeout', '$browser', '$$rAF', + function($delegate, $$asyncCallback, $timeout, $browser, $$rAF) { var animate = { queue: [], cancel: $delegate.cancel, enabled: $delegate.enabled, triggerCallbackEvents: function() { + $$rAF.flush(); $$asyncCallback.flush(); }, triggerCallbackPromise: function() { @@ -1757,7 +1758,7 @@ angular.mock.$RAFDecorator = ['$delegate', function($delegate) { queue[i](); } - queue = []; + queue = queue.slice(i); }; return rafFn; diff --git a/test/.jshintrc b/test/.jshintrc index 18ef9d956730..0d85795b3545 100644 --- a/test/.jshintrc +++ b/test/.jshintrc @@ -146,6 +146,7 @@ "they": false, "tthey": false, "xthey": false, + "assertCompareNodes": false, /* e2e */ "browser": false, @@ -165,6 +166,7 @@ "provideLog": false, "spyOnlyCallsWithArgs": false, "createMockStyleSheet": false, + "browserSupportsCssAnimations": false, "browserTrigger": false, "jqLiteCacheSize": false } diff --git a/test/helpers/privateMocks.js b/test/helpers/privateMocks.js index 521b0c3abde5..f733afb8393f 100644 --- a/test/helpers/privateMocks.js +++ b/test/helpers/privateMocks.js @@ -1,6 +1,11 @@ 'use strict'; /* globals xit */ +function assertCompareNodes(a,b,not) { + a = a[0] ? a[0] : a; + b = b[0] ? b[0] : b; + expect(a === b).toBe(!not); +} function baseThey(msg, vals, spec, itFn) { var valsIsArray = angular.isArray(vals); @@ -26,7 +31,14 @@ function xthey(msg, vals, spec) { baseThey(msg, vals, spec, xit); } - +function browserSupportsCssAnimations() { + var nav = window.navigator.appVersion; + if (nav.indexOf('MSIE') >= 0) { + var version = parseInt(navigator.appVersion.match(/MSIE ([\d.]+)/)[1]); + return version >= 10; //only IE10+ support keyframes / transitions + } + return true; +} function createMockStyleSheet(doc, wind) { doc = doc ? doc[0] : document; diff --git a/test/helpers/testabilityPatch.js b/test/helpers/testabilityPatch.js index ef03ad6bff8a..74fd2f76add6 100644 --- a/test/helpers/testabilityPatch.js +++ b/test/helpers/testabilityPatch.js @@ -37,6 +37,17 @@ beforeEach(function() { afterEach(function() { var count, cache; + // both of these nodes are persisted across tests + // and therefore the hashCode may be cached + var node = document.querySelector('html'); + if (node) { + node.$$hashKey = null; + } + var bod = document.body; + if (bod) { + bod.$$hashKey = null; + } + if (this.$injector) { var $rootScope = this.$injector.get('$rootScope'); var $rootElement = this.$injector.get('$rootElement'); diff --git a/test/ng/animateSpec.js b/test/ng/animateSpec.js index ed7d17d3b98a..f1ae31686f82 100644 --- a/test/ng/animateSpec.js +++ b/test/ng/animateSpec.js @@ -82,12 +82,14 @@ describe("$animate", function() { expect($animate.leave(element)).toBeAPromise(); })); - it("should provide noop `enabled` and `cancel` methods", inject(function($animate) { - expect($animate.enabled).toBe(angular.noop); + it("should provide the `enabled` and `cancel` methods", inject(function($animate) { expect($animate.enabled()).toBeUndefined(); + expect($animate.cancel({})).toBeUndefined(); + })); - expect($animate.cancel).toBe(angular.noop); - expect($animate.cancel()).toBeUndefined(); + it("should provide the `on` and `off` methods", inject(function($animate) { + expect(isFunction($animate.on)).toBe(true); + expect(isFunction($animate.off)).toBe(true); })); it("should add and remove classes on SVG elements", inject(function($animate, $rootScope) { @@ -175,6 +177,30 @@ describe("$animate", function() { expect(style.color).toBe('green'); expect(style.borderColor).toBe('purple'); })); + + it("should avoid cancelling out add/remove when the element already contains the class", + inject(function($animate, $rootScope) { + + var element = jqLite('
'); + + $animate.addClass(element, 'ng-hide'); + $animate.removeClass(element, 'ng-hide'); + $rootScope.$digest(); + + expect(element).not.toHaveClass('ng-hide'); + })); + + it("should avoid cancelling out remove/add if the element does not contain the class", + inject(function($animate, $rootScope) { + + var element = jqLite('
'); + + $animate.removeClass(element, 'ng-hide'); + $animate.addClass(element, 'ng-hide'); + $rootScope.$digest(); + + expect(element).toHaveClass('ng-hide'); + })); }); describe('CSS class DOM manipulation', function() { @@ -190,26 +216,27 @@ describe("$animate", function() { function setupClassManipulationSpies() { inject(function($animate) { - addClass = spyOn($animate, '$$addClassImmediately').andCallThrough(); - removeClass = spyOn($animate, '$$removeClassImmediately').andCallThrough(); + addClass = spyOn(window, 'jqLiteAddClass').andCallThrough(); + removeClass = spyOn(window, 'jqLiteRemoveClass').andCallThrough(); }); } function setupClassManipulationLogger(log) { - inject(function($animate) { - var addClassImmediately = $animate.$$addClassImmediately; - var removeClassImmediately = $animate.$$removeClassImmediately; - addClass = spyOn($animate, '$$addClassImmediately').andCallFake(function(element, classes) { + inject(function() { + var _addClass = jqLiteAddClass; + addClass = spyOn(window, 'jqLiteAddClass').andCallFake(function(element, classes) { var names = classes; if (Object.prototype.toString.call(classes) === '[object Array]') names = classes.join(' '); log('addClass(' + names + ')'); - return addClassImmediately.call($animate, element, classes); + return _addClass(element, classes); }); - removeClass = spyOn($animate, '$$removeClassImmediately').andCallFake(function(element, classes) { + + var _removeClass = jqLiteRemoveClass; + removeClass = spyOn(window, 'jqLiteRemoveClass').andCallFake(function(element, classes) { var names = classes; if (Object.prototype.toString.call(classes) === '[object Array]') names = classes.join(' '); log('removeClass(' + names + ')'); - return removeClassImmediately.call($animate, element, classes); + return _removeClass(element, classes); }); }); } @@ -281,7 +308,7 @@ describe("$animate", function() { })); - it('should return a promise which is resolved on a different turn', inject(function(log, $animate, $browser, $rootScope) { + it('should return a promise which is resolved on a different turn', inject(function(log, $animate, $$rAF, $rootScope) { element = jqLite('

test

'); $animate.addClass(element, 'test1').then(log.fn('addClass(test1)')); @@ -289,7 +316,8 @@ describe("$animate", function() { $rootScope.$digest(); expect(log).toEqual([]); - $browser.defer.flush(); + $$rAF.flush(); + $rootScope.$digest(); expect(log).toEqual(['addClass(test1)', 'removeClass(test2)']); log.reset(); @@ -298,10 +326,10 @@ describe("$animate", function() { $rootScope.$apply(function() { $animate.addClass(element, 'test3').then(log.fn('addClass(test3)')); $animate.removeClass(element, 'test4').then(log.fn('removeClass(test4)')); - expect(log).toEqual([]); }); - $browser.defer.flush(); + $$rAF.flush(); + $rootScope.$digest(); expect(log).toEqual(['addClass(test3)', 'removeClass(test4)']); })); diff --git a/test/ng/directive/formSpec.js b/test/ng/directive/formSpec.js index cd74f9defba1..27d18f3032e0 100644 --- a/test/ng/directive/formSpec.js +++ b/test/ng/directive/formSpec.js @@ -802,6 +802,7 @@ describe('form', function() { scope.$digest(); expect(form).toBePristine(); scope.$digest(); + expect(formCtrl.$pristine).toBe(true); expect(formCtrl.$dirty).toBe(false); expect(nestedForm).toBePristine(); diff --git a/test/ng/directive/ngClassSpec.js b/test/ng/directive/ngClassSpec.js index 0967aa5898fa..f9f8f044ad89 100644 --- a/test/ng/directive/ngClassSpec.js +++ b/test/ng/directive/ngClassSpec.js @@ -425,14 +425,13 @@ describe('ngClass animations', function() { }); }); - it("should consider the ngClass expression evaluation before performing an animation", function() { + it("should combine the ngClass evaluation with the enter animation", function() { //mocks are not used since the enter delegation method is called before addClass and //it makes it impossible to test to see that addClass is called first module('ngAnimate'); module('ngAnimateMock'); - var digestQueue = []; module(function($animateProvider) { $animateProvider.register('.crazy', function() { return { @@ -442,25 +441,9 @@ describe('ngClass animations', function() { } }; }); - - return function($rootScope) { - var before = $rootScope.$$postDigest; - $rootScope.$$postDigest = function() { - var args = arguments; - digestQueue.push(function() { - before.apply($rootScope, args); - }); - }; - }; }); - inject(function($compile, $rootScope, $browser, $rootElement, $animate, $timeout, $document) { - - // Animations need to digest twice in order to be enabled regardless if there are no template HTTP requests. - $rootScope.$digest(); - digestQueue.shift()(); - - $rootScope.$digest(); - digestQueue.shift()(); + inject(function($compile, $rootScope, $browser, $rootElement, $animate, $timeout, $document, $$rAF) { + $animate.enabled(true); $rootScope.val = 'crazy'; element = angular.element('
'); @@ -478,25 +461,13 @@ describe('ngClass animations', function() { expect(element.hasClass('crazy')).toBe(false); expect(enterComplete).toBe(false); - expect(digestQueue.length).toBe(1); $rootScope.$digest(); - - $timeout.flush(); - - expect(element.hasClass('crazy')).toBe(true); - expect(enterComplete).toBe(false); - - digestQueue.shift()(); //enter - expect(digestQueue.length).toBe(0); - - //we don't normally need this, but since the timing between digests - //is spaced-out then it is required so that the original digestion - //is kicked into gear + $$rAF.flush(); $rootScope.$digest(); - $animate.triggerCallbacks(); - expect(element.data('state')).toBe('crazy-enter'); + expect(element.hasClass('crazy')).toBe(true); expect(enterComplete).toBe(true); + expect(element.data('state')).toBe('crazy-enter'); }); }); diff --git a/test/ng/directive/ngModelSpec.js b/test/ng/directive/ngModelSpec.js index 438fef1325e4..a5beb214f784 100644 --- a/test/ng/directive/ngModelSpec.js +++ b/test/ng/directive/ngModelSpec.js @@ -1156,17 +1156,17 @@ describe('ngModel', function() { it('should minimize janky setting of classes during $validate() and ngModelWatch', inject(function($animate, $compile, $rootScope) { - var addClass = $animate.$$addClassImmediately; - var removeClass = $animate.$$removeClassImmediately; + var addClass = $animate.addClass; + var removeClass = $animate.removeClass; var addClassCallCount = 0; var removeClassCallCount = 0; var input; - $animate.$$addClassImmediately = function(element, className) { + $animate.addClass = function(element, className) { if (input && element[0] === input[0]) ++addClassCallCount; return addClass.call($animate, element, className); }; - $animate.$$removeClassImmediately = function(element, className) { + $animate.removeClass = function(element, className) { if (input && element[0] === input[0]) ++removeClassCallCount; return removeClass.call($animate, element, className); }; diff --git a/test/ng/directive/ngRepeatSpec.js b/test/ng/directive/ngRepeatSpec.js index 1205a8701b9f..c4377dcab160 100644 --- a/test/ng/directive/ngRepeatSpec.js +++ b/test/ng/directive/ngRepeatSpec.js @@ -1462,7 +1462,7 @@ describe('ngRepeat animations', function() { })); it('should not change the position of the block that is being animated away via a leave animation', - inject(function($compile, $rootScope, $animate, $document, $window, $sniffer, $timeout) { + inject(function($compile, $rootScope, $animate, $document, $window, $sniffer, $timeout, $$rAF) { if (!$sniffer.transitions) return; var item; @@ -1487,10 +1487,9 @@ describe('ngRepeat animations', function() { $rootScope.$digest(); expect(element.text()).toBe('123'); // the original order should be preserved - $animate.triggerReflow(); + $$rAF.flush(); $timeout.flush(1500); // 1s * 1.5 closing buffer expect(element.text()).toBe('13'); - } finally { ss.destroy(); } diff --git a/test/ngAnimate/.jshintrc b/test/ngAnimate/.jshintrc new file mode 100644 index 000000000000..b307fb405952 --- /dev/null +++ b/test/ngAnimate/.jshintrc @@ -0,0 +1,13 @@ +{ + "extends": "../.jshintrc", + "browser": true, + "newcap": false, + "globals": { + "mergeAnimationOptions": false, + "prepareAnimationOptions": false, + "applyAnimationStyles": false, + "applyAnimationFromStyles": false, + "applyAnimationToStyles": false, + "applyAnimationClassesFactory": false + } +} diff --git a/test/ngAnimate/animateCssDriverSpec.js b/test/ngAnimate/animateCssDriverSpec.js new file mode 100644 index 000000000000..81a9e14cda42 --- /dev/null +++ b/test/ngAnimate/animateCssDriverSpec.js @@ -0,0 +1,894 @@ +'use strict'; + +describe("ngAnimate $$animateCssDriver", function() { + + beforeEach(module('ngAnimate')); + + function int(x) { + return parseInt(x, 10); + } + + function hasAll(array, vals) { + for (var i = 0; i < vals.length; i++) { + if (array.indexOf(vals[i]) === -1) return false; + } + return true; + } + + it('should return a noop driver handler if the browser does not support CSS transitions and keyframes', function() { + module(function($provide) { + $provide.value('$sniffer', {}); + }); + inject(function($$animateCssDriver) { + expect($$animateCssDriver).toBe(noop); + }); + }); + + describe('when active', function() { + if (!browserSupportsCssAnimations()) return; + + var element; + var ss; + afterEach(function() { + dealoc(element); + if (ss) { + ss.destroy(); + } + }); + + var capturedAnimation; + var captureLog; + var driver; + var captureFn; + beforeEach(module(function($provide) { + capturedAnimation = null; + captureLog = []; + captureFn = noop; + + $provide.factory('$animateCss', function($$AnimateRunner) { + return function() { + var runner = new $$AnimateRunner(); + + capturedAnimation = arguments; + captureFn.apply(null, arguments); + captureLog.push({ + element: arguments[0], + args: arguments, + runner: runner + }); + + return { + start: function() { + return runner; + } + }; + }; + }); + + element = jqLite('
'); + + return function($$animateCssDriver, $document, $window) { + driver = $$animateCssDriver; + ss = createMockStyleSheet($document, $window); + }; + })); + + it('should register the $$animateCssDriver into the list of drivers found in $animateProvider', + module(function($animateProvider) { + + expect($animateProvider.drivers).toContain('$$animateCssDriver'); + })); + + it('should register the $$animateCssDriver into the list of drivers found in $animateProvider', + module(function($animateProvider) { + + expect($animateProvider.drivers).toContain('$$animateCssDriver'); + })); + + describe("regular animations", function() { + it("should render an animation on the given element", inject(function() { + driver({ element: element }); + expect(capturedAnimation[0]).toBe(element); + })); + + it("should return an object with a start function", inject(function() { + var runner = driver({ element: element }); + expect(isFunction(runner.start)).toBeTruthy(); + })); + }); + + describe("anchored animations", function() { + var from, to, fromAnimation, toAnimation; + + beforeEach(module(function() { + return function($rootElement, $document) { + from = element; + to = jqLite('
'); + fromAnimation = { element: from, event: 'enter' }; + toAnimation = { element: to, event: 'leave' }; + $rootElement.append(from); + $rootElement.append(to); + + // we need to do this so that style detection works + jqLite($document[0].body).append($rootElement); + }; + })); + + it("should not return anything if no animation is detected", function() { + module(function($provide) { + $provide.value('$animateCss', noop); + }); + inject(function() { + var runner = driver({ + from: fromAnimation, + to: toAnimation + }); + expect(runner).toBeFalsy(); + }); + }); + + it("should return a start method", inject(function() { + var animator = driver({ + from: fromAnimation, + to: toAnimation + }); + expect(isFunction(animator.start)).toBeTruthy(); + })); + + they("should return a runner with a $prop() method which will end the animation", + ['end', 'cancel'], function(method) { + + var closeAnimation; + module(function($provide) { + $provide.factory('$animateCss', function($q, $$AnimateRunner) { + return function() { + return { + start: function() { + return new $$AnimateRunner({ + end: function() { + closeAnimation(); + } + }); + } + }; + }; + }); + }); + + inject(function() { + var animator = driver({ + from: fromAnimation, + to: toAnimation + }); + + var animationClosed = false; + closeAnimation = function() { + animationClosed = true; + }; + + var runner = animator.start(); + + expect(isFunction(runner[method])).toBe(true); + runner[method](); + expect(animationClosed).toBe(true); + }); + }); + + it("should end the animation for each of the from and to elements as well as all the anchors", function() { + var closeLog = {}; + module(function($provide) { + $provide.factory('$animateCss', function($q, $$AnimateRunner) { + return function(element, options) { + var type = options.event || 'anchor'; + closeLog[type] = closeLog[type] || []; + return { + start: function() { + return new $$AnimateRunner({ + end: function() { + closeLog[type].push(element); + } + }); + } + }; + }; + }); + }); + + inject(function() { + //we'll just use one animation to make the test smaller + var anchorAnimation = { + 'in': jqLite('
'), + 'out': jqLite('
') + }; + + fromAnimation.element.append(anchorAnimation['out']); + toAnimation.element.append(anchorAnimation['in']); + + var animator = driver({ + from: fromAnimation, + to: toAnimation, + anchors: [ + anchorAnimation, + anchorAnimation, + anchorAnimation + ] + }); + + var runner = animator.start(); + runner.end(); + + expect(closeLog.enter[0]).toEqual(fromAnimation.element); + expect(closeLog.leave[0]).toEqual(toAnimation.element); + expect(closeLog.anchor.length).toBe(3); + }); + }); + + it("should render an animation on both the from and to elements", inject(function() { + captureFn = function(element, details) { + element.addClass(details.event); + }; + + var runner = driver({ + from: fromAnimation, + to: toAnimation + }); + + expect(captureLog.length).toBe(2); + expect(fromAnimation.element).toHaveClass('enter'); + expect(toAnimation.element).toHaveClass('leave'); + })); + + it("should start the animations on the from and to elements in parallel", function() { + var animationLog = []; + module(function($provide) { + $provide.factory('$animateCss', function($$AnimateRunner) { + return function(element, details) { + return { + start: function() { + animationLog.push([element, details.event]); + return new $$AnimateRunner(); + } + }; + }; + }); + }); + inject(function() { + var runner = driver({ + from: fromAnimation, + to: toAnimation + }); + + expect(animationLog.length).toBe(0); + runner.start(); + expect(animationLog).toEqual([ + [fromAnimation.element, 'enter'], + [toAnimation.element, 'leave'] + ]); + }); + }); + + it("should start an animation for each anchor", inject(function() { + var o1 = jqLite('
'); + from.append(o1); + var o2 = jqLite('
'); + from.append(o2); + var o3 = jqLite('
'); + from.append(o3); + + var i1 = jqLite('
'); + to.append(i1); + var i2 = jqLite('
'); + to.append(i2); + var i3 = jqLite('
'); + to.append(i3); + + var anchors = [ + { 'out': o1, 'in': i1, classes: 'red' }, + { 'out': o2, 'in': i2, classes: 'blue' }, + { 'out': o2, 'in': i2, classes: 'green' } + ]; + + var runner = driver({ + from: fromAnimation, + to: toAnimation, + anchors: anchors + }); + + expect(captureLog.length).toBe(5); + })); + + it("should create a clone of the starting element for each anchor animation", inject(function() { + var o1 = jqLite('
'); + from.append(o1); + var o2 = jqLite('
'); + from.append(o2); + + var i1 = jqLite('
'); + to.append(i1); + var i2 = jqLite('
'); + to.append(i2); + + var anchors = [ + { 'out': o1, 'in': i1 }, + { 'out': o2, 'in': i2 } + ]; + + var runner = driver({ + from: fromAnimation, + to: toAnimation, + anchors: anchors + }); + + var a2 = captureLog.pop().element; + var a1 = captureLog.pop().element; + + expect(a1).not.toEqual(o1); + expect(a1.attr('class')).toMatch(/\bout1\b/); + expect(a2).not.toEqual(o2); + expect(a2.attr('class')).toMatch(/\bout2\b/); + })); + + it("should create a clone of the starting element and place it at the end of the $rootElement container", + inject(function($rootElement) { + + //stick some garbage into the rootElement + $rootElement.append(jqLite('
')); + $rootElement.append(jqLite('
')); + $rootElement.append(jqLite('
')); + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + var toAnchor = jqLite('
'); + to.append(toAnchor); + + var runner = driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'in': fromAnchor, + 'out': toAnchor + }] + }); + + var anchor = captureLog.pop().element; + var anchorNode = anchor[0]; + var contents = $rootElement.contents(); + + expect(contents.length).toBeGreaterThan(1); + expect(contents[contents.length - 1]).toEqual(anchorNode); + })); + + it("should first do an addClass('ng-anchor-out') animation on the cloned anchor", inject(function($rootElement) { + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + var runner = driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }); + + var anchorDetails = captureLog.pop().args[1]; + expect(anchorDetails.addClass).toBe('ng-anchor-out'); + expect(anchorDetails.event).toBeFalsy(); + })); + + it("should then do an addClass('ng-anchor-in') animation on the cloned anchor and remove the old class", + inject(function($rootElement, $$rAF) { + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + var runner = driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }).start(); + + captureLog.pop().runner.end(); + $$rAF.flush(); + + var anchorDetails = captureLog.pop().args[1]; + expect(anchorDetails.removeClass.trim()).toBe('ng-anchor-out'); + expect(anchorDetails.addClass.trim()).toBe('ng-anchor-in'); + expect(anchorDetails.event).toBeFalsy(); + })); + + it("should provide an explicit delay setting in the options provided to $animateCss for anchor animations", + inject(function($rootElement) { + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + var runner = driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }); + + expect(capturedAnimation[1].delay).toBeTruthy(); + })); + + it("should begin the anchor animation by seeding the from styles based on where the from anchor element is positioned", + inject(function($rootElement) { + + ss.addRule('.starting-element', 'width:200px; height:100px; display:block;'); + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + var runner = driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }); + + var anchorAnimation = captureLog.pop(); + var anchorElement = anchorAnimation.element; + var anchorDetails = anchorAnimation.args[1]; + + var fromStyles = anchorDetails.from; + expect(int(fromStyles.width)).toBe(200); + expect(int(fromStyles.height)).toBe(100); + // some browsers have their own body margin defaults + expect(int(fromStyles.top)).toBeGreaterThan(499); + expect(int(fromStyles.left)).toBeGreaterThan(149); + })); + + it("should append a `px` value for all seeded animation styles", inject(function($rootElement, $$rAF) { + ss.addRule('.starting-element', 'width:10px; height:20px; display:inline-block;'); + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + var runner = driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }); + + var anchorAnimation = captureLog.pop(); + var anchorDetails = anchorAnimation.args[1]; + + forEach(anchorDetails.from, function(value) { + expect(value.substr(value.length - 2)).toBe('px'); + }); + + // the out animation goes first + anchorAnimation.runner.end(); + $$rAF.flush(); + + anchorAnimation = captureLog.pop(); + anchorDetails = anchorAnimation.args[1]; + + forEach(anchorDetails.to, function(value) { + expect(value.substr(value.length - 2)).toBe('px'); + }); + })); + + it("should then do an removeClass('out') + addClass('in') animation on the cloned anchor", + inject(function($rootElement, $$rAF) { + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }).start(); + + // the out animation goes first + captureLog.pop().runner.end(); + $$rAF.flush(); + + var anchorDetails = captureLog.pop().args[1]; + expect(anchorDetails.removeClass).toMatch(/\bout\b/); + expect(anchorDetails.addClass).toMatch(/\bin\b/); + expect(anchorDetails.event).toBeFalsy(); + })); + + it("should add the `ng-animate-anchor` class to the cloned anchor element", + inject(function($rootElement, $$rAF) { + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }).start(); + + var clonedAnchor = captureLog.pop().element; + expect(clonedAnchor).toHaveClass('ng-animate-anchor'); + })); + + it("should add and remove the `ng-animate-shim` class on the in anchor element during the animation", + inject(function($rootElement, $$rAF) { + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }).start(); + + expect(fromAnchor).toHaveClass('ng-animate-shim'); + + // the out animation goes first + captureLog.pop().runner.end(); + $$rAF.flush(); + captureLog.pop().runner.end(); + + expect(fromAnchor).not.toHaveClass('ng-animate-shim'); + })); + + it("should add and remove the `ng-animate-shim` class on the out anchor element during the animation", + inject(function($rootElement, $$rAF) { + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }).start(); + + expect(toAnchor).toHaveClass('ng-animate-shim'); + + // the out animation goes first + captureLog.pop().runner.end(); + $$rAF.flush(); + + expect(toAnchor).toHaveClass('ng-animate-shim'); + captureLog.pop().runner.end(); + + expect(toAnchor).not.toHaveClass('ng-animate-shim'); + })); + + it("should create the cloned anchor with all of the classes from the from anchor element", + inject(function($rootElement, $$rAF) { + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }).start(); + + var addedClasses = captureLog.pop().element.attr('class').split(' '); + expect(hasAll(addedClasses, ['yes', 'no', 'maybe'])).toBe(true); + })); + + it("should remove the classes of the starting anchor from the cloned anchor node during the in animation and also add the classes of the destination anchor within the same animation", + inject(function($rootElement, $$rAF) { + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }).start(); + + // the out animation goes first + captureLog.pop().runner.end(); + $$rAF.flush(); + + var anchorDetails = captureLog.pop().args[1]; + var removedClasses = anchorDetails.removeClass.split(' '); + var addedClasses = anchorDetails.addClass.split(' '); + + expect(hasAll(removedClasses, ['yes', 'no', 'maybe'])).toBe(true); + expect(hasAll(addedClasses, ['why', 'ok', 'so-what'])).toBe(true); + })); + + it("should not attempt to add/remove any classes that contain a `ng-` prefix", + inject(function($rootElement, $$rAF) { + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }).start(); + + // the out animation goes first + captureLog.pop().runner.end(); + $$rAF.flush(); + + var inAnimation = captureLog.pop(); + var details = inAnimation.args[1]; + + var addedClasses = details.addClass.split(' '); + var removedClasses = details.removeClass.split(' '); + + expect(addedClasses).not.toContain('ng-foo'); + expect(addedClasses).not.toContain('ng-bar'); + + expect(removedClasses).not.toContain('ng-yes'); + expect(removedClasses).not.toContain('ng-no'); + })); + + it("should not remove any shared CSS classes between the starting and destination anchor element during the in animation", + inject(function($rootElement, $$rAF) { + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }).start(); + + // the out animation goes first + captureLog.pop().runner.end(); + $$rAF.flush(); + + var outAnimation = captureLog.pop(); + var clonedAnchor = outAnimation.element; + var details = outAnimation.args[1]; + + var addedClasses = details.addClass.split(' '); + var removedClasses = details.removeClass.split(' '); + + expect(hasAll(addedClasses, ['brown', 'black'])).toBe(true); + expect(hasAll(removedClasses, ['green'])).toBe(true); + + expect(addedClasses).not.toContain('red'); + expect(addedClasses).not.toContain('blue'); + + expect(removedClasses).not.toContain('brown'); + expect(removedClasses).not.toContain('black'); + + expect(clonedAnchor).toHaveClass('red'); + expect(clonedAnchor).toHaveClass('blue'); + })); + + it("should continue the anchor animation by seeding the to styles based on where the final anchor element will be positioned", + inject(function($rootElement, $$rAF) { + ss.addRule('.ending-element', 'width:9999px; height:6666px; display:inline-block;'); + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }).start(); + + captureLog.pop().runner.end(); + $$rAF.flush(); + + var anchorAnimation = captureLog.pop(); + var anchorElement = anchorAnimation.element; + var anchorDetails = anchorAnimation.args[1]; + + var toStyles = anchorDetails.to; + expect(int(toStyles.width)).toBe(9999); + expect(int(toStyles.height)).toBe(6666); + // some browsers have their own body margin defaults + expect(int(toStyles.top)).toBeGreaterThan(300); + expect(int(toStyles.left)).toBeGreaterThan(20); + })); + + it("should remove the cloned anchor node from the DOM once the 'in' animation is complete", + inject(function($rootElement, $$rAF) { + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }).start(); + + // the out animation goes first + var inAnimation = captureLog.pop(); + var clonedAnchor = inAnimation.element; + expect(clonedAnchor.parent().length).toBe(1); + inAnimation.runner.end(); + $$rAF.flush(); + + // now the in animation completes + expect(clonedAnchor.parent().length).toBe(1); + captureLog.pop().runner.end(); + + expect(clonedAnchor.parent().length).toBe(0); + })); + + it("should pass the provided domOperation into $animateCss to be run right after the element is animated if a leave animation is present", + inject(function($rootElement, $$rAF) { + + toAnimation.event = 'enter'; + fromAnimation.event = 'leave'; + + var leaveOp = function() { }; + fromAnimation.domOperation = leaveOp; + + driver({ + from: fromAnimation, + to: toAnimation + }).start(); + + var leaveAnimation = captureLog.shift(); + var enterAnimation = captureLog.shift(); + + expect(leaveAnimation.args[1].onDone).toBe(leaveOp); + expect(enterAnimation.args[1].onDone).toBeUndefined(); + })); + + it("should fire the returned runner promise when the from, to and anchor animations are all complete", + inject(function($rootElement, $rootScope, $$rAF) { + + ss.addRule('.ending-element', 'width:9999px; height:6666px; display:inline-block;'); + + var fromAnchor = jqLite('
'); + from.append(fromAnchor); + + var toAnchor = jqLite('
'); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + var completed = false; + driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }).start().then(function() { + completed = true; + }); + + captureLog.pop().runner.end(); //from + captureLog.pop().runner.end(); //to + captureLog.pop().runner.end(); //anchor(out) + captureLog.pop().runner.end(); //anchor(in) + $$rAF.flush(); + $rootScope.$digest(); + + expect(completed).toBe(true); + })); + }); + }); +}); diff --git a/test/ngAnimate/animateCssSpec.js b/test/ngAnimate/animateCssSpec.js new file mode 100644 index 000000000000..afcc52efbf40 --- /dev/null +++ b/test/ngAnimate/animateCssSpec.js @@ -0,0 +1,2428 @@ +'use strict'; + +describe("ngAnimate $animateCss", function() { + + beforeEach(module('ngAnimate')); + + function assertAnimationRunning(element, not) { + var className = element.attr('class'); + var regex = /\b\w+-active\b/; + not ? expect(className).toMatch(regex) + : expect(className).not.toMatch(regex); + } + + var fakeStyle = { + color: 'blue' + }; + + var ss, prefix, triggerAnimationStartFrame; + beforeEach(module(function() { + return function($document, $window, $sniffer, $$rAF) { + prefix = '-' + $sniffer.vendorPrefix.toLowerCase() + '-'; + ss = createMockStyleSheet($document, $window); + triggerAnimationStartFrame = function() { + $$rAF.flush(); + }; + }; + })); + + afterEach(function() { + if (ss) { + ss.destroy(); + } + }); + + it("should return false if neither transitions or keyframes are supported by the browser", + inject(function($animateCss, $sniffer, $rootElement, $document) { + + var animator; + var element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + $sniffer.transitions = $sniffer.animations = false; + animator = $animateCss(element, { + duration: 10, + to: { 'background': 'red' } + }); + expect(animator).toBeFalsy(); + })); + + describe('when active', function() { + if (!browserSupportsCssAnimations()) return; + + describe("rAF usage", function() { + it("should buffer all requests into a single requestAnimationFrame call", + inject(function($animateCss, $$rAF, $rootScope, $document, $rootElement) { + + jqLite($document[0].body).append($rootElement); + + var count = 0; + var runners = []; + function makeRequest() { + var element = jqLite('
'); + $rootElement.append(element); + var runner = $animateCss(element, { duration: 5, to: fakeStyle }).start(); + runner.then(function() { + count++; + }); + runners.push(runner); + } + + makeRequest(); + makeRequest(); + makeRequest(); + + expect(count).toBe(0); + + triggerAnimationStartFrame(); + forEach(runners, function(runner) { + runner.end(); + }); + + $rootScope.$digest(); + expect(count).toBe(3); + })); + + it("should cancel previous requests to rAF to avoid premature flushing", function() { + var count = 0; + module(function($provide) { + $provide.value('$$rAF', function() { + return function cancellationFn() { + count++; + }; + }); + }); + inject(function($animateCss, $$rAF, $document, $rootElement) { + jqLite($document[0].body).append($rootElement); + + function makeRequest() { + var element = jqLite('
'); + $rootElement.append(element); + $animateCss(element, { duration: 5, to: fakeStyle }).start(); + } + + makeRequest(); + makeRequest(); + makeRequest(); + expect(count).toBe(2); + }); + }); + }); + + describe("animator and runner", function() { + var animationDuration = 5; + var element, animator; + beforeEach(inject(function($animateCss, $rootElement, $document) { + element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + animator = $animateCss(element, { + event: 'enter', + structural: true, + duration: animationDuration, + to: fakeStyle + }); + })); + + it('should expose start and end functions for the animator object', inject(function() { + expect(typeof animator.start).toBe('function'); + expect(typeof animator.end).toBe('function'); + })); + + it('should expose end, cancel, resume and pause methods on the runner object', inject(function() { + var runner = animator.start(); + triggerAnimationStartFrame(); + + expect(typeof runner.end).toBe('function'); + expect(typeof runner.cancel).toBe('function'); + expect(typeof runner.resume).toBe('function'); + expect(typeof runner.pause).toBe('function'); + })); + + it('should start the animation', inject(function() { + expect(element).not.toHaveClass('ng-enter-active'); + animator.start(); + triggerAnimationStartFrame(); + + expect(element).toHaveClass('ng-enter-active'); + })); + + it('should end the animation when called from the animator object', inject(function() { + animator.start(); + triggerAnimationStartFrame(); + + animator.end(); + expect(element).not.toHaveClass('ng-enter-active'); + })); + + it('should end the animation when called from the runner object', inject(function() { + var runner = animator.start(); + triggerAnimationStartFrame(); + runner.end(); + expect(element).not.toHaveClass('ng-enter-active'); + })); + + it('should permanently close the animation if closed before the next rAF runs', inject(function() { + var runner = animator.start(); + runner.end(); + + triggerAnimationStartFrame(); + expect(element).not.toHaveClass('ng-enter-active'); + })); + + it('should return a runner object at the start of the animation that contains a `then` method', + inject(function($rootScope) { + + var runner = animator.start(); + triggerAnimationStartFrame(); + + expect(isPromiseLike(runner)).toBeTruthy(); + + var resolved; + runner.then(function() { + resolved = true; + }); + + runner.end(); + $rootScope.$digest(); + expect(resolved).toBeTruthy(); + })); + + it('should cancel the animation and reject', inject(function($rootScope) { + var rejected; + var runner = animator.start(); + triggerAnimationStartFrame(); + + runner.then(noop, function() { + rejected = true; + }); + + runner.cancel(); + $rootScope.$digest(); + expect(rejected).toBeTruthy(); + })); + + it('should run pause, but not effect the transition animation', inject(function() { + var blockingDelay = '-' + animationDuration + 's'; + + expect(element.css('transition-delay')).toEqual(blockingDelay); + var runner = animator.start(); + triggerAnimationStartFrame(); + + expect(element.css('transition-delay')).not.toEqual(blockingDelay); + runner.pause(); + expect(element.css('transition-delay')).not.toEqual(blockingDelay); + })); + + it('should pause the transition, have no effect, but not end it', inject(function() { + var runner = animator.start(); + triggerAnimationStartFrame(); + + runner.pause(); + + browserTrigger(element, 'transitionend', + { timeStamp: Date.now(), elapsedTime: 5 }); + + expect(element).toHaveClass('ng-enter-active'); + })); + + it('should resume the animation', inject(function() { + var runner = animator.start(); + triggerAnimationStartFrame(); + + runner.pause(); + + browserTrigger(element, 'transitionend', + { timeStamp: Date.now(), elapsedTime: 5 }); + + expect(element).toHaveClass('ng-enter-active'); + runner.resume(); + + expect(element).not.toHaveClass('ng-enter-active'); + })); + + it('should pause and resume a keyframe animation using animation-play-state', + inject(function($animateCss) { + + element.attr('style', ''); + ss.addRule('.ng-enter', '-webkit-animation:1.5s keyframe_animation;' + + 'animation:1.5s keyframe_animation;'); + + animator = $animateCss(element, { + event: 'enter', + structural: true + }); + + var runner = animator.start(); + triggerAnimationStartFrame(); + + runner.pause(); + expect(element.css(prefix + 'animation-play-state')).toEqual('paused'); + runner.resume(); + expect(element.attr('style')).toBeFalsy(); + })); + + it('should remove the animation-play-state style if the animation is closed', + inject(function($animateCss) { + + element.attr('style', ''); + ss.addRule('.ng-enter', '-webkit-animation:1.5s keyframe_animation;' + + 'animation:1.5s keyframe_animation;'); + + animator = $animateCss(element, { + event: 'enter', + structural: true + }); + + var runner = animator.start(); + triggerAnimationStartFrame(); + + runner.pause(); + expect(element.css(prefix + 'animation-play-state')).toEqual('paused'); + runner.end(); + expect(element.attr('style')).toBeFalsy(); + })); + }); + + describe("CSS", function() { + describe("detected styles", function() { + var element, options; + + function assertAnimationComplete(bool) { + var assert = expect(element); + if (bool) { + assert = assert.not; + } + assert.toHaveClass('ng-enter'); + assert.toHaveClass('ng-enter-active'); + } + + function keyframeProgress(element, duration, delay) { + browserTrigger(element, 'animationend', + { timeStamp: Date.now() + ((delay || 1) * 1000), elapsedTime: duration }); + } + + function transitionProgress(element, duration, delay) { + browserTrigger(element, 'transitionend', + { timeStamp: Date.now() + ((delay || 1) * 1000), elapsedTime: duration }); + } + + beforeEach(inject(function($rootElement, $document) { + element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + options = { event: 'enter', structural: true }; + })); + + it("should use the highest transition duration value detected in the CSS class", inject(function($animateCss) { + ss.addRule('.ng-enter', 'transition:1s linear all;' + + 'transition-duration:10s, 15s, 20s;'); + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + transitionProgress(element, 10); + assertAnimationComplete(false); + + transitionProgress(element, 15); + assertAnimationComplete(false); + + transitionProgress(element, 20); + assertAnimationComplete(true); + })); + + it("should use the highest transition delay value detected in the CSS class", inject(function($animateCss) { + ss.addRule('.ng-enter', 'transition:1s linear all;' + + 'transition-delay:10s, 15s, 20s;'); + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + transitionProgress(element, 1, 10); + assertAnimationComplete(false); + + transitionProgress(element, 1, 15); + assertAnimationComplete(false); + + transitionProgress(element, 1, 20); + assertAnimationComplete(true); + })); + + it("should only close when both the animation delay and duration have passed", + inject(function($animateCss) { + + ss.addRule('.ng-enter', 'transition:10s 5s linear all;'); + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + transitionProgress(element, 10, 2); + assertAnimationComplete(false); + + transitionProgress(element, 9, 6); + assertAnimationComplete(false); + + transitionProgress(element, 10, 5); + assertAnimationComplete(true); + })); + + it("should use the highest keyframe duration value detected in the CSS class", inject(function($animateCss) { + ss.addRule('.ng-enter', 'animation:animation 1s, animation 2s, animation 3s;' + + '-webkit-animation:animation 1s, animation 2s, animation 3s;'); + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + keyframeProgress(element, 1); + assertAnimationComplete(false); + + keyframeProgress(element, 2); + assertAnimationComplete(false); + + keyframeProgress(element, 3); + assertAnimationComplete(true); + })); + + it("should use the highest keyframe delay value detected in the CSS class", inject(function($animateCss) { + ss.addRule('.ng-enter', 'animation:animation 1s 2s, animation 1s 10s, animation 1s 1000ms;' + + '-webkit-animation:animation 1s 2s, animation 1s 10s, animation 1s 1000ms;'); + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + keyframeProgress(element, 1, 1); + assertAnimationComplete(false); + + keyframeProgress(element, 1, 2); + assertAnimationComplete(false); + + keyframeProgress(element, 1, 10); + assertAnimationComplete(true); + })); + + it("should use the highest keyframe duration value detected in the CSS class with respect to the animation-iteration-count property", inject(function($animateCss) { + ss.addRule('.ng-enter', + 'animation:animation 1s 2s 3, animation 1s 10s 2, animation 1s 1000ms infinite;' + + '-webkit-animation:animation 1s 2s 3, animation 1s 10s 2, animation 1s 1000ms infinite;'); + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + keyframeProgress(element, 1, 1); + assertAnimationComplete(false); + + keyframeProgress(element, 1, 2); + assertAnimationComplete(false); + + keyframeProgress(element, 3, 10); + assertAnimationComplete(true); + })); + + it("should use the highest duration value when both transitions and keyframes are used", inject(function($animateCss) { + ss.addRule('.ng-enter', 'transition:1s linear all;' + + 'transition-duration:10s, 15s, 20s;' + + 'animation:animation 1s, animation 2s, animation 3s 0s 7;' + + '-webkit-animation:animation 1s, animation 2s, animation 3s 0s 7;'); + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + transitionProgress(element, 10); + keyframeProgress(element, 10); + assertAnimationComplete(false); + + transitionProgress(element, 15); + keyframeProgress(element, 15); + assertAnimationComplete(false); + + transitionProgress(element, 20); + keyframeProgress(element, 20); + assertAnimationComplete(false); + + // 7 * 3 = 21 + transitionProgress(element, 21); + keyframeProgress(element, 21); + assertAnimationComplete(true); + })); + + it("should use the highest delay value when both transitions and keyframes are used", inject(function($animateCss) { + ss.addRule('.ng-enter', 'transition:1s linear all;' + + 'transition-delay:10s, 15s, 20s;' + + 'animation:animation 1s 2s, animation 1s 16s, animation 1s 19s;' + + '-webkit-animation:animation 1s 2s, animation 1s 16s, animation 1s 19s;'); + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + transitionProgress(element, 1, 10); + keyframeProgress(element, 1, 10); + assertAnimationComplete(false); + + transitionProgress(element, 1, 16); + keyframeProgress(element, 1, 16); + assertAnimationComplete(false); + + transitionProgress(element, 1, 19); + keyframeProgress(element, 1, 19); + assertAnimationComplete(false); + + transitionProgress(element, 1, 20); + keyframeProgress(element, 1, 20); + assertAnimationComplete(true); + })); + }); + + describe("staggering", function() { + it("should apply a stagger based when an active ng-EVENT-stagger class with a transition-delay is detected", + inject(function($animateCss, $document, $rootElement, $timeout) { + + jqLite($document[0].body).append($rootElement); + + ss.addRule('.ng-enter-stagger', 'transition-delay:0.2s'); + ss.addRule('.ng-enter', 'transition:2s linear all'); + + var elements = []; + var i; + var elm; + + for (i = 0; i < 5; i++) { + elm = jqLite('
'); + elements.push(elm); + $rootElement.append(elm); + + $animateCss(elm, { event: 'enter', structural: true }).start(); + expect(elm).not.toHaveClass('ng-enter-stagger'); + expect(elm).toHaveClass('ng-enter'); + } + + triggerAnimationStartFrame(); + + expect(elements[0]).toHaveClass('ng-enter-active'); + for (i = 1; i < 5; i++) { + elm = elements[i]; + + expect(elm).not.toHaveClass('ng-enter-active'); + $timeout.flush(200); + expect(elm).toHaveClass('ng-enter-active'); + + browserTrigger(elm, 'transitionend', + { timeStamp: Date.now() + 1000, elapsedTime: 2 }); + + expect(elm).not.toHaveClass('ng-enter'); + expect(elm).not.toHaveClass('ng-enter-active'); + expect(elm).not.toHaveClass('ng-enter-stagger'); + } + })); + + it("should apply a stagger based when for all provided addClass/removeClass CSS classes", + inject(function($animateCss, $document, $rootElement, $timeout) { + + jqLite($document[0].body).append($rootElement); + + ss.addRule('.red-add-stagger,' + + '.blue-remove-stagger,' + + '.green-add-stagger', 'transition-delay:0.2s'); + + ss.addRule('.red-add,' + + '.blue-remove,' + + '.green-add', 'transition:2s linear all'); + + var elements = []; + var i; + var elm; + + for (i = 0; i < 5; i++) { + elm = jqLite('
'); + elements.push(elm); + $rootElement.append(elm); + + $animateCss(elm, { + addClass: 'red green', + removeClass: 'blue' + }).start(); + } + + triggerAnimationStartFrame(); + for (i = 0; i < 5; i++) { + elm = elements[i]; + + expect(elm).not.toHaveClass('red-add-stagger'); + expect(elm).not.toHaveClass('green-add-stagger'); + expect(elm).not.toHaveClass('blue-remove-stagger'); + + expect(elm).toHaveClass('red-add'); + expect(elm).toHaveClass('green-add'); + expect(elm).toHaveClass('blue-remove'); + } + + expect(elements[0]).toHaveClass('red-add-active'); + expect(elements[0]).toHaveClass('green-add-active'); + expect(elements[0]).toHaveClass('blue-remove-active'); + for (i = 1; i < 5; i++) { + elm = elements[i]; + + expect(elm).not.toHaveClass('red-add-active'); + expect(elm).not.toHaveClass('green-add-active'); + expect(elm).not.toHaveClass('blue-remove-active'); + + $timeout.flush(200); + + expect(elm).toHaveClass('red-add-active'); + expect(elm).toHaveClass('green-add-active'); + expect(elm).toHaveClass('blue-remove-active'); + + browserTrigger(elm, 'transitionend', + { timeStamp: Date.now() + 1000, elapsedTime: 2 }); + + expect(elm).not.toHaveClass('red-add-active'); + expect(elm).not.toHaveClass('green-add-active'); + expect(elm).not.toHaveClass('blue-remove-active'); + + expect(elm).not.toHaveClass('red-add-stagger'); + expect(elm).not.toHaveClass('green-add-stagger'); + expect(elm).not.toHaveClass('blue-remove-stagger'); + } + })); + + it("should block the transition animation between start and animate when staggered", + inject(function($animateCss, $document, $rootElement) { + + jqLite($document[0].body).append($rootElement); + + ss.addRule('.ng-enter-stagger', 'transition-delay:0.2s'); + ss.addRule('.ng-enter', 'transition:2s linear all;'); + + var element; + var i; + var elms = []; + + for (i = 0; i < 5; i++) { + element = jqLite('
'); + $rootElement.append(element); + + $animateCss(element, { event: 'enter', structural: true }).start(); + elms.push(element); + } + + triggerAnimationStartFrame(); + for (i = 0; i < 5; i++) { + element = elms[i]; + if (i === 0) { + expect(element.attr('style')).toBeFalsy(); + } else { + expect(element.css('transition-delay')).toContain('-2s'); + } + } + })); + + it("should block (pause) the keyframe animation between start and animate when staggered", + inject(function($animateCss, $document, $rootElement) { + + jqLite($document[0].body).append($rootElement); + + ss.addRule('.ng-enter-stagger', prefix + 'animation-delay:0.2s'); + ss.addRule('.ng-enter', prefix + 'animation:my_animation 2s;'); + + var i, element, elements = []; + for (i = 0; i < 5; i++) { + element = jqLite('
'); + $rootElement.append(element); + + $animateCss(element, { event: 'enter', structural: true }).start(); + elements.push(element); + } + + triggerAnimationStartFrame(); + + for (i = 0; i < 5; i++) { + element = elements[i]; + if (i === 0) { // the first element is always run right away + expect(element.attr('style')).toBeFalsy(); + } else { + expect(element.css(prefix + 'animation-play-state')).toBe('paused'); + } + } + })); + + it("should not apply a stagger if the transition delay value is inherited from a earlier CSS class", + inject(function($animateCss, $document, $rootElement) { + + jqLite($document[0].body).append($rootElement); + + ss.addRule('.transition-animation', 'transition:2s 5s linear all;'); + + for (var i = 0; i < 5; i++) { + var element = jqLite('
'); + $rootElement.append(element); + + $animateCss(element, { event: 'enter', structural: true }).start(); + triggerAnimationStartFrame(); + + + expect(element).toHaveClass('ng-enter-active'); + } + })); + + it("should apply a stagger only if the transition duration value is zero when inherited from a earlier CSS class", + inject(function($animateCss, $document, $rootElement) { + + jqLite($document[0].body).append($rootElement); + + ss.addRule('.transition-animation', 'transition:2s 5s linear all;'); + ss.addRule('.transition-animation.ng-enter-stagger', + 'transition-duration:0s; transition-delay:0.2s;'); + + var element, i, elms = []; + for (i = 0; i < 5; i++) { + element = jqLite('
'); + $rootElement.append(element); + + elms.push(element); + $animateCss(element, { event: 'enter', structural: true }).start(); + } + + triggerAnimationStartFrame(); + for (i = 1; i < 5; i++) { + element = elms[i]; + expect(element).not.toHaveClass('ng-enter-active'); + } + })); + + + it("should ignore animation staggers if only transition animations were detected", + inject(function($animateCss, $document, $rootElement) { + + jqLite($document[0].body).append($rootElement); + + ss.addRule('.ng-enter-stagger', prefix + 'animation-delay:0.2s'); + ss.addRule('.transition-animation', 'transition:2s 5s linear all;'); + + for (var i = 0; i < 5; i++) { + var element = jqLite('
'); + $rootElement.append(element); + + $animateCss(element, { event: 'enter', structural: true }).start(); + triggerAnimationStartFrame(); + + + expect(element).toHaveClass('ng-enter-active'); + } + })); + + it("should ignore transition staggers if only keyframe animations were detected", + inject(function($animateCss, $document, $rootElement) { + + jqLite($document[0].body).append($rootElement); + + ss.addRule('.ng-enter-stagger', 'transition-delay:0.2s'); + ss.addRule('.transition-animation', prefix + 'animation:2s 5s my_animation;'); + + for (var i = 0; i < 5; i++) { + var elm = jqLite('
'); + $rootElement.append(elm); + + var animator = $animateCss(elm, { event: 'enter', structural: true }).start(); + triggerAnimationStartFrame(); + + + expect(elm).toHaveClass('ng-enter-active'); + } + })); + + it("should start on the highest stagger value if both transition and keyframe staggers are used together", + inject(function($animateCss, $document, $rootElement, $timeout, $browser) { + + jqLite($document[0].body).append($rootElement); + + ss.addRule('.ng-enter-stagger', 'transition-delay:0.5s;' + + prefix + 'animation-delay:1s'); + + ss.addRule('.ng-enter', 'transition:10s linear all;' + + prefix + 'animation:my_animation 20s'); + + var i, elm, elements = []; + for (i = 0; i < 5; i++) { + elm = jqLite('
'); + elements.push(elm); + $rootElement.append(elm); + + $animateCss(elm, { event: 'enter', structural: true }).start(); + + expect(elm).toHaveClass('ng-enter'); + } + + triggerAnimationStartFrame(); + + expect(elements[0]).toHaveClass('ng-enter-active'); + for (i = 1; i < 5; i++) { + elm = elements[i]; + + expect(elm).not.toHaveClass('ng-enter-active'); + + $timeout.flush(500); + expect(elm).not.toHaveClass('ng-enter-active'); + + $timeout.flush(500); + expect(elm).toHaveClass('ng-enter-active'); + } + })); + + it("should apply the closing timeout ontop of the stagger timeout", + inject(function($animateCss, $document, $rootElement, $timeout, $browser) { + + jqLite($document[0].body).append($rootElement); + + ss.addRule('.ng-enter-stagger', 'transition-delay:1s;'); + ss.addRule('.ng-enter', 'transition:10s linear all;'); + + var elm, i, elms = []; + for (i = 0; i < 5; i++) { + elm = jqLite('
'); + elms.push(elm); + $rootElement.append(elm); + + $animateCss(elm, { event: 'enter', structural: true }).start(); + triggerAnimationStartFrame(); + } + + for (i = 1; i < 2; i++) { + elm = elms[i]; + expect(elm).toHaveClass('ng-enter'); + $timeout.flush(1000); + $timeout.flush(15000); + expect(elm).not.toHaveClass('ng-enter'); + } + })); + + it("should apply the closing timeout ontop of the stagger timeout with an added delay", + inject(function($animateCss, $document, $rootElement, $timeout, $browser) { + + jqLite($document[0].body).append($rootElement); + + ss.addRule('.ng-enter-stagger', 'transition-delay:1s;'); + ss.addRule('.ng-enter', 'transition:10s linear all; transition-delay:50s;'); + + var elm, i, elms = []; + for (i = 0; i < 5; i++) { + elm = jqLite('
'); + elms.push(elm); + $rootElement.append(elm); + + $animateCss(elm, { event: 'enter', structural: true }).start(); + triggerAnimationStartFrame(); + } + + for (i = 1; i < 2; i++) { + elm = elms[i]; + expect(elm).toHaveClass('ng-enter'); + $timeout.flush(1000); + $timeout.flush(65000); + expect(elm).not.toHaveClass('ng-enter'); + } + })); + + it("should issue a stagger if a stagger value is provided in the options", + inject(function($animateCss, $document, $rootElement, $timeout) { + + jqLite($document[0].body).append($rootElement); + ss.addRule('.ng-enter', 'transition:2s linear all'); + + var elm, i, elements = []; + for (i = 0; i < 5; i++) { + elm = jqLite('
'); + elements.push(elm); + $rootElement.append(elm); + + $animateCss(elm, { + event: 'enter', + structural: true, + stagger: 0.5 + }).start(); + expect(elm).toHaveClass('ng-enter'); + } + + triggerAnimationStartFrame(); + + expect(elements[0]).toHaveClass('ng-enter-active'); + for (i = 1; i < 5; i++) { + elm = elements[i]; + + expect(elm).not.toHaveClass('ng-enter-active'); + $timeout.flush(500); + expect(elm).toHaveClass('ng-enter-active'); + + browserTrigger(elm, 'transitionend', + { timeStamp: Date.now() + 1000, elapsedTime: 2 }); + + expect(elm).not.toHaveClass('ng-enter'); + expect(elm).not.toHaveClass('ng-enter-active'); + expect(elm).not.toHaveClass('ng-enter-stagger'); + } + })); + + it("should only add/remove classes once the stagger timeout has passed", + inject(function($animateCss, $document, $rootElement, $timeout) { + + jqLite($document[0].body).append($rootElement); + + var element = jqLite('
'); + $rootElement.append(element); + + $animateCss(element, { + addClass: 'red', + removeClass: 'green', + duration: 5, + stagger: 0.5, + staggerIndex: 3 + }).start(); + + triggerAnimationStartFrame(); + expect(element).toHaveClass('green'); + expect(element).not.toHaveClass('red'); + + $timeout.flush(1500); + expect(element).not.toHaveClass('green'); + expect(element).toHaveClass('red'); + })); + }); + + describe("closing timeout", function() { + it("should close off the animation after 150% of the animation time has passed", + inject(function($animateCss, $document, $rootElement, $timeout) { + + ss.addRule('.ng-enter', 'transition:10s linear all;'); + + var element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + var animator = $animateCss(element, { event: 'enter', structural: true }); + animator.start(); + triggerAnimationStartFrame(); + + + expect(element).toHaveClass('ng-enter'); + expect(element).toHaveClass('ng-enter-active'); + + $timeout.flush(15000); + + expect(element).not.toHaveClass('ng-enter'); + expect(element).not.toHaveClass('ng-enter-active'); + })); + + it("should close off the animation after 150% of the animation time has passed and consider the detected delay value", + inject(function($animateCss, $document, $rootElement, $timeout) { + + ss.addRule('.ng-enter', 'transition:10s linear all; transition-delay:30s;'); + + var element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + var animator = $animateCss(element, { event: 'enter', structural: true }); + animator.start(); + triggerAnimationStartFrame(); + + + expect(element).toHaveClass('ng-enter'); + expect(element).toHaveClass('ng-enter-active'); + + $timeout.flush(45000); + + expect(element).not.toHaveClass('ng-enter'); + expect(element).not.toHaveClass('ng-enter-active'); + })); + + it("should still resolve the animation once expired", + inject(function($animateCss, $document, $rootElement, $timeout) { + + ss.addRule('.ng-enter', 'transition:10s linear all;'); + + var element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + var animator = $animateCss(element, { event: 'enter', structural: true }); + + var failed, passed; + animator.start().then(function() { + passed = true; + }, function() { + failed = true; + }); + + triggerAnimationStartFrame(); + $timeout.flush(15000); + expect(passed).toBe(true); + })); + + it("should not resolve/reject after passing if the animation completed successfully", + inject(function($animateCss, $document, $rootElement, $timeout, $rootScope) { + + ss.addRule('.ng-enter', 'transition:10s linear all;'); + + var element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + var animator = $animateCss(element, { event: 'enter', structural: true }); + + var failed, passed; + animator.start().then( + function() { + passed = true; + }, + function() { + failed = true; + } + ); + triggerAnimationStartFrame(); + + browserTrigger(element, 'transitionend', + { timeStamp: Date.now() + 1000, elapsedTime: 10 }); + + $rootScope.$digest(); + + expect(passed).toBe(true); + expect(failed).not.toBe(true); + + $timeout.flush(15000); + + expect(passed).toBe(true); + expect(failed).not.toBe(true); + })); + }); + + describe("getComputedStyle", function() { + var count; + var acceptableTimingsData = { + transitionDuration: "10s" + }; + + beforeEach(module(function($provide) { + count = {}; + $provide.value('$window', extend({}, window, { + document: jqLite(window.document), + getComputedStyle: function(node) { + var key = node.className.indexOf('stagger') >= 0 + ? 'stagger' : 'normal'; + count[key] = count[key] || 0; + count[key]++; + return acceptableTimingsData; + } + })); + + return function($document, $rootElement) { + jqLite($document[0].body).append($rootElement); + }; + })); + + it("should cache frequent calls to getComputedStyle before the next animation frame kicks in", + inject(function($animateCss, $document, $rootElement, $$rAF) { + + var i, elm, animator; + for (i = 0; i < 5; i++) { + elm = jqLite('
'); + $rootElement.append(elm); + animator = $animateCss(elm, { event: 'enter', structural: true }); + var runner = animator.start(); + } + + expect(count.normal).toBe(1); + + for (i = 0; i < 5; i++) { + elm = jqLite('
'); + $rootElement.append(elm); + animator = $animateCss(elm, { event: 'enter', structural: true }); + animator.start(); + } + + expect(count.normal).toBe(1); + triggerAnimationStartFrame(); + + expect(count.normal).toBe(2); + + for (i = 0; i < 5; i++) { + elm = jqLite('
'); + $rootElement.append(elm); + animator = $animateCss(elm, { event: 'enter', structural: true }); + animator.start(); + } + + expect(count.normal).toBe(3); + })); + + it("should cache frequent calls to getComputedStyle for stagger animations before the next animation frame kicks in", + inject(function($animateCss, $document, $rootElement, $$rAF) { + + var element = jqLite('
'); + $rootElement.append(element); + var animator = $animateCss(element, { event: 'enter', structural: true }); + animator.start(); + triggerAnimationStartFrame(); + + expect(count.stagger).toBeUndefined(); + + var i, elm; + for (i = 0; i < 5; i++) { + elm = jqLite('
'); + $rootElement.append(elm); + animator = $animateCss(elm, { event: 'enter', structural: true }); + animator.start(); + } + + expect(count.stagger).toBe(1); + + for (i = 0; i < 5; i++) { + elm = jqLite('
'); + $rootElement.append(elm); + animator = $animateCss(elm, { event: 'enter', structural: true }); + animator.start(); + } + + expect(count.stagger).toBe(1); + $$rAF.flush(); + + for (i = 0; i < 5; i++) { + elm = jqLite('
'); + $rootElement.append(elm); + animator = $animateCss(elm, { event: 'enter', structural: true }); + animator.start(); + } + + triggerAnimationStartFrame(); + expect(count.stagger).toBe(2); + })); + }); + }); + + it('should apply a custom temporary class when a non-structural animation is used', + inject(function($animateCss, $rootElement, $document) { + + var element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + $animateCss(element, { + event: 'super', + duration: 1000, + to: fakeStyle + }).start(); + expect(element).toHaveClass('super'); + + triggerAnimationStartFrame(); + expect(element).toHaveClass('super-active'); + })); + + describe("structural animations", function() { + they('should decorate the element with the ng-$prop CSS class', + ['enter', 'leave', 'move'], function(event) { + inject(function($animateCss, $rootElement, $document) { + var element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + $animateCss(element, { + event: event, + structural: true, + duration: 1000, + to: fakeStyle + }); + expect(element).toHaveClass('ng-' + event); + }); + }); + + they('should decorate the element with the ng-$prop-active CSS class', + ['enter', 'leave', 'move'], function(event) { + inject(function($animateCss, $rootElement, $document) { + var element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + var animator = $animateCss(element, { + event: event, + structural: true, + duration: 1000, + to: fakeStyle + }); + + animator.start(); + triggerAnimationStartFrame(); + + expect(element).toHaveClass('ng-' + event + '-active'); + }); + }); + + they('should remove the ng-$prop and ng-$prop-active CSS classes from the element once the animation is done', + ['enter', 'leave', 'move'], function(event) { + inject(function($animateCss, $rootElement, $document) { + var element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + var animator = $animateCss(element, { + event: event, + structural: true, + duration: 1, + to: fakeStyle + }); + + animator.start(); + triggerAnimationStartFrame(); + + + browserTrigger(element, 'transitionend', + { timeStamp: Date.now() + 1000, elapsedTime: 1 }); + + expect(element).not.toHaveClass('ng-' + event); + expect(element).not.toHaveClass('ng-' + event + '-active'); + }); + }); + + they('should allow additional CSS classes to be added and removed alongside the $prop animation', + ['enter', 'leave', 'move'], function(event) { + inject(function($animateCss, $rootElement) { + var element = jqLite('
'); + $rootElement.append(element); + var animator = $animateCss(element, { + event: event, + structural: true, + duration: 1, + to: fakeStyle, + addClass: 'red', + removeClass: 'green' + }); + + animator.start(); + triggerAnimationStartFrame(); + + expect(element).toHaveClass('ng-' + event); + expect(element).toHaveClass('ng-' + event + '-active'); + + expect(element).toHaveClass('red'); + expect(element).toHaveClass('red-add'); + expect(element).toHaveClass('red-add-active'); + + expect(element).not.toHaveClass('green'); + expect(element).toHaveClass('green-remove'); + expect(element).toHaveClass('green-remove-active'); + }); + }); + + they('should place a CSS transition block after the preparation function to block accidental style changes', + ['enter', 'leave', 'move', 'addClass', 'removeClass'], function(event) { + + inject(function($animateCss, $rootElement, $document) { + var element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + ss.addRule('.cool-animation', 'transition:1.5s linear all;'); + element.addClass('cool-animation'); + + var data = {}; + if (event === 'addClass') { + data.addClass = 'green'; + } else if (event === 'removeClass') { + element.addClass('red'); + data.removeClass = 'red'; + } else { + data.event = event; + } + + var animator = $animateCss(element, data); + expect(element.css('transition-delay')).toMatch('-1.5s'); + animator.start(); + triggerAnimationStartFrame(); + + expect(element.attr('style')).toBeFalsy(); + }); + }); + + they('should not place a CSS transition block if options.skipBlocking is provided', + ['enter', 'leave', 'move', 'addClass', 'removeClass'], function(event) { + + inject(function($animateCss, $rootElement, $document) { + var element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + ss.addRule('.cool-animation', 'transition:1.5s linear all;'); + element.addClass('cool-animation'); + + var data = {}; + if (event === 'addClass') { + data.addClass = 'green'; + } else if (event === 'removeClass') { + element.addClass('red'); + data.removeClass = 'red'; + } else { + data.event = event; + } + + data.skipBlocking = true; + var animator = $animateCss(element, data); + + expect(element.attr('style')).toBeFalsy(); + animator.start(); + triggerAnimationStartFrame(); + + expect(element.attr('style')).toBeFalsy(); + }); + }); + + they('should place a CSS transition block after the preparation function even if a duration is provided', + ['enter', 'leave', 'move', 'addClass', 'removeClass'], function(event) { + + inject(function($animateCss, $rootElement, $document) { + var element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + ss.addRule('.cool-animation', 'transition:1.5s linear all;'); + element.addClass('cool-animation'); + + var data = {}; + if (event === 'addClass') { + data.addClass = 'green'; + } else if (event === 'removeClass') { + element.addClass('red'); + data.removeClass = 'red'; + } else { + data.event = event; + } + + data.duration = 10; + var animator = $animateCss(element, data); + + expect(element.css('transition-delay')).toMatch('-10s'); + expect(element.css('transition-duration')).toMatch(''); + animator.start(); + triggerAnimationStartFrame(); + + + expect(element.attr('style')).not.toContain('transition-delay'); + expect(element.css('transition-property')).toContain('all'); + expect(element.css('transition-duration')).toContain('10s'); + }); + }); + + it('should allow multiple events to be animated at the same time', + inject(function($animateCss, $rootElement, $document) { + + var element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + $animateCss(element, { + event: ['enter', 'leave', 'move'], + structural: true, + duration: 1, + to: fakeStyle + }).start(); + triggerAnimationStartFrame(); + + + expect(element).toHaveClass('ng-enter'); + expect(element).toHaveClass('ng-leave'); + expect(element).toHaveClass('ng-move'); + + expect(element).toHaveClass('ng-enter-active'); + expect(element).toHaveClass('ng-leave-active'); + expect(element).toHaveClass('ng-move-active'); + + browserTrigger(element, 'transitionend', + { timeStamp: Date.now() + 1000, elapsedTime: 1 }); + + expect(element).not.toHaveClass('ng-enter'); + expect(element).not.toHaveClass('ng-leave'); + expect(element).not.toHaveClass('ng-move'); + expect(element).not.toHaveClass('ng-enter-active'); + expect(element).not.toHaveClass('ng-leave-active'); + expect(element).not.toHaveClass('ng-move-active'); + })); + }); + + describe("class-based animations", function() { + they('should decorate the element with the class-$prop CSS class', + ['add', 'remove'], function(event) { + inject(function($animateCss, $rootElement) { + var element = jqLite('
'); + $rootElement.append(element); + + var options = {}; + options[event + 'Class'] = 'class'; + options.duration = 1000; + options.to = fakeStyle; + $animateCss(element, options); + expect(element).toHaveClass('class-' + event); + }); + }); + + they('should decorate the element with the class-$prop-active CSS class', + ['add', 'remove'], function(event) { + inject(function($animateCss, $rootElement) { + var element = jqLite('
'); + $rootElement.append(element); + + var options = {}; + options[event + 'Class'] = 'class'; + options.duration = 1000; + options.to = fakeStyle; + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + expect(element).toHaveClass('class-' + event + '-active'); + }); + }); + + they('should remove the class-$prop-add and class-$prop-active CSS classes from the element once the animation is done', + ['enter', 'leave', 'move'], function(event) { + inject(function($animateCss, $rootElement, $document) { + var element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + var options = {}; + options.event = event; + options.duration = 10; + options.to = fakeStyle; + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + browserTrigger(element, 'transitionend', + { timeStamp: Date.now() + 1000, elapsedTime: 10 }); + + expect(element).not.toHaveClass('ng-' + event); + expect(element).not.toHaveClass('ng-' + event + '-active'); + }); + }); + + they('should allow the class duration styles to be recalculated once started if the CSS classes being applied result new transition styles', + ['add', 'remove'], function(event) { + inject(function($animateCss, $rootElement, $document) { + + var element = jqLite('
'); + + if (event == 'add') { + ss.addRule('.natural-class', 'transition:1s linear all;'); + } else { + ss.addRule('.natural-class', 'transition:0s linear none;'); + ss.addRule('.base-class', 'transition:1s linear none;'); + + element.addClass('base-class'); + element.addClass('natural-class'); + } + + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + var options = {}; + options[event + 'Class'] = 'natural-class'; + var runner = $animateCss(element, options); + runner.start(); + triggerAnimationStartFrame(); + + expect(element).toHaveClass('natural-class-' + event); + expect(element).toHaveClass('natural-class-' + event + '-active'); + + browserTrigger(element, 'transitionend', + { timeStamp: Date.now(), elapsedTime: 1 }); + + expect(element).not.toHaveClass('natural-class-' + event); + expect(element).not.toHaveClass('natural-class-' + event + '-active'); + }); + }); + + they('should force the class-based values to be applied early if no transition/keyframe is detected at all', + ['enter', 'leave', 'move'], function(event) { + inject(function($animateCss, $rootElement, $document) { + + ss.addRule('.blue.ng-' + event, 'transition:2s linear all;'); + + var element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + var runner = $animateCss(element, { + addClass: 'blue', + removeClass: 'red', + event: event, + structural: true + }); + + runner.start(); + expect(element).toHaveClass('ng-' + event); + expect(element).toHaveClass('blue'); + expect(element).not.toHaveClass('red'); + + triggerAnimationStartFrame(); + expect(element).toHaveClass('ng-' + event); + expect(element).toHaveClass('ng-' + event + '-active'); + expect(element).toHaveClass('blue'); + expect(element).not.toHaveClass('red'); + + browserTrigger(element, 'transitionend', + { timeStamp: Date.now(), elapsedTime: 2 }); + + expect(element).not.toHaveClass('ng-' + event); + expect(element).not.toHaveClass('ng-' + event + '-active'); + expect(element).toHaveClass('blue'); + expect(element).not.toHaveClass('red'); + }); + }); + }); + + describe("options", function() { + var element; + beforeEach(inject(function($rootElement, $document) { + jqLite($document[0].body).append($rootElement); + + element = jqLite('
'); + $rootElement.append(element); + })); + + describe("[duration]", function() { + it("should be applied for a transition directly", inject(function($animateCss, $rootElement) { + var element = jqLite('
'); + $rootElement.append(element); + + var options = { + duration: 3000, + to: fakeStyle, + event: 'enter', + structural: true + }; + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + var style = element.attr('style'); + expect(style).toContain('3000s'); + expect(style).toContain('linear'); + })); + + it("should be applied to a CSS keyframe animation directly if keyframes are detected within the CSS class", + inject(function($animateCss, $rootElement) { + + ss.addRule('.ng-enter', '-webkit-animation:1.5s keyframe_animation;' + + 'animation:1.5s keyframe_animation;'); + + var options = { + duration: 5, + event: 'enter', + structural: true + }; + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + expect(element.css(prefix + 'animation-duration')).toEqual('5s'); + })); + + it("should remove all inline keyframe styling when an animation completes if a custom duration was applied", + inject(function($animateCss, $rootElement) { + + ss.addRule('.ng-enter', '-webkit-animation:1.5s keyframe_animation;' + + 'animation:1.5s keyframe_animation;'); + + var options = { + duration: 5, + event: 'enter', + structural: true + }; + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + browserTrigger(element, 'animationend', + { timeStamp: Date.now() + 5000, elapsedTime: 5 }); + + expect(element.attr('style')).toBeFalsy(); + })); + + it("should remove all inline keyframe delay styling when an animation completes if a custom duration was applied", + inject(function($animateCss, $rootElement) { + + ss.addRule('.ng-enter', '-webkit-animation:1.5s keyframe_animation;' + + 'animation:1.5s keyframe_animation;'); + + var options = { + delay: 5, + event: 'enter', + structural: true + }; + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + expect(element.css(prefix + 'animation-delay')).toEqual('5s'); + + browserTrigger(element, 'animationend', + { timeStamp: Date.now() + 5000, elapsedTime: 1.5 }); + + expect(element.attr('style')).toBeFalsy(); + })); + + it("should not prepare the animation at all if a duration of zero is provided", + inject(function($animateCss, $rootElement) { + + ss.addRule('.ng-enter', '-webkit-transition:1s linear all;' + + 'transition:1s linear all;'); + + var options = { + duration: 0, + event: 'enter', + structural: true + }; + var animator = $animateCss(element, options); + expect(animator).toBeFalsy(); + })); + + it("should apply a transition and keyframe duration directly if both transitions and keyframe classes are detected", + inject(function($animateCss, $rootElement) { + + ss.addRule('.ng-enter', '-webkit-animation:3s keyframe_animation;' + + 'animation:3s keyframe_animation;' + + 'transition:5s linear all;'); + + var options = { + duration: 4, + event: 'enter', + structural: true + }; + var animator = $animateCss(element, options); + + animator.start(); + triggerAnimationStartFrame(); + + var style = element.attr('style'); + expect(style).toMatch(/animation(?:-duration)?:\s*4s/); + expect(element.css('transition-duration')).toMatch('4s'); + expect(element.css('transition-property')).toMatch('all'); + expect(style).toContain('linear'); + })); + }); + + describe("[delay]", function() { + it("should be applied for a transition directly", inject(function($animateCss, $rootElement) { + var element = jqLite('
'); + $rootElement.append(element); + + var options = { + duration: 3000, + delay: 500, + to: fakeStyle, + event: 'enter', + structural: true + }; + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + var prop = element.css('transition-delay'); + expect(prop).toEqual('500s'); + })); + + it("should return false for the animator if a delay is provided but not a duration", + inject(function($animateCss, $rootElement) { + + var element = jqLite('
'); + $rootElement.append(element); + + var options = { + delay: 500, + to: fakeStyle, + event: 'enter', + structural: true + }; + + var animator = $animateCss(element, options); + expect(animator).toBeFalsy(); + })); + + it("should override the delay value present in the CSS class", + inject(function($animateCss, $rootElement) { + + ss.addRule('.ng-enter', '-webkit-transition:1s linear all;' + + 'transition:1s linear all;' + + '-webkit-transition-delay:10s;' + + 'transition-delay:10s;'); + + var element = jqLite('
'); + $rootElement.append(element); + + var options = { + delay: 500, + event: 'enter', + structural: true + }; + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + var prop = element.css('transition-delay'); + expect(prop).toEqual('500s'); + })); + + it("should allow the delay value to zero if provided", + inject(function($animateCss, $rootElement) { + + ss.addRule('.ng-enter', '-webkit-transition:1s linear all;' + + 'transition:1s linear all;' + + '-webkit-transition-delay:10s;' + + 'transition-delay:10s;'); + + var element = jqLite('
'); + $rootElement.append(element); + + var options = { + delay: 0, + event: 'enter', + structural: true + }; + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + var prop = element.css('transition-delay'); + expect(prop).toEqual('0s'); + })); + + it("should be applied to a CSS keyframe animation if detected within the CSS class", + inject(function($animateCss, $rootElement) { + + ss.addRule('.ng-enter', '-webkit-animation:1.5s keyframe_animation;' + + 'animation:1.5s keyframe_animation;'); + + var options = { + delay: 400, + event: 'enter', + structural: true + }; + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + expect(element.css(prefix + 'animation-delay')).toEqual('400s'); + expect(element.attr('style')).not.toContain('transition-delay'); + })); + + it("should apply a transition and keyframe delay if both transitions and keyframe classes are detected", + inject(function($animateCss, $rootElement) { + + ss.addRule('.ng-enter', '-webkit-animation:3s keyframe_animation;' + + 'animation:3s keyframe_animation;' + + 'transition:5s linear all;'); + + var options = { + delay: 10, + event: 'enter', + structural: true + }; + var animator = $animateCss(element, options); + + expect(element.css('transition-delay')).toContain('-5s'); + expect(element.attr('style')).not.toContain('animation-delay'); + animator.start(); + triggerAnimationStartFrame(); + + + expect(element.css(prefix + 'animation-delay')).toEqual('10s'); + expect(element.css('transition-delay')).toEqual('10s'); + })); + + it("should apply blocking before the animation starts, but then apply the detected delay when options.delay is true", + inject(function($animateCss, $rootElement) { + + ss.addRule('.ng-enter', 'transition:2s linear all; transition-delay: 1s;'); + + var options = { + delay: true, + event: 'enter', + structural: true + }; + + var animator = $animateCss(element, options); + expect(element.css('transition-delay')).toEqual('-2s'); + + animator.start(); + triggerAnimationStartFrame(); + + expect(element.css('transition-delay')).toEqual('1s'); + })); + + they("should consider a negative value when delay:true is used with a $prop animation", { + 'transition': function() { + return { + prop: 'transition-delay', + css: 'transition:2s linear all; transition-delay: -1s' + }; + }, + 'keyframe': function(prefix) { + return { + prop: prefix + 'animation-delay', + css: prefix + 'animation:2s keyframe_animation; ' + prefix + 'animation-delay: -1s;' + }; + } + }, function(testDetailsFactory) { + inject(function($animateCss, $rootElement) { + var testDetails = testDetailsFactory(prefix); + + ss.addRule('.ng-enter', testDetails.css); + var options = { + delay: true, + event: 'enter', + structural: true + }; + + var animator = $animateCss(element, options); + + animator.start(); + triggerAnimationStartFrame(); + + expect(element.css(testDetails.prop)).toContain('-1s'); + }); + }); + + they("should consider a negative value when a negative option delay is provided for a $prop animation", { + 'transition': function() { + return { + prop: 'transition-delay', + css: 'transition:2s linear all' + }; + }, + 'keyframe': function(prefix) { + return { + prop: prefix + 'animation-delay', + css: prefix + 'animation:2s keyframe_animation' + }; + } + }, function(testDetailsFactory) { + inject(function($animateCss, $rootElement) { + var testDetails = testDetailsFactory(prefix); + + ss.addRule('.ng-enter', testDetails.css); + var options = { + delay: -2, + event: 'enter', + structural: true + }; + + var animator = $animateCss(element, options); + + animator.start(); + triggerAnimationStartFrame(); + + expect(element.css(testDetails.prop)).toContain('-2s'); + }); + }); + + they("should expect the $propend event to always return the full duration even when negative values are used", { + 'transition': function() { + return { + event: 'transitionend', + css: 'transition:5s linear all; transition-delay: -2s' + }; + }, + 'animation': function(prefix) { + return { + event: 'animationend', + css: prefix + 'animation:5s keyframe_animation; ' + prefix + 'animation-delay: -2s;' + }; + } + }, function(testDetailsFactory) { + inject(function($animateCss, $rootElement) { + var testDetails = testDetailsFactory(prefix); + var event = testDetails.event; + + ss.addRule('.ng-enter', testDetails.css); + var options = { event: 'enter', structural: true }; + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + // 5 + (-2s) = 3 + browserTrigger(element, event, { timeStamp: Date.now(), elapsedTime: 3 }); + + assertAnimationRunning(element, true); + + // 5 seconds is the full animation + browserTrigger(element, event, { timeStamp: Date.now(), elapsedTime: 5 }); + + assertAnimationRunning(element); + }); + }); + }); + + describe("[transtionStyle]", function() { + it("should apply the transition directly onto the element and animate accordingly", + inject(function($animateCss, $rootElement) { + + var options = { + transitionStyle: '5.5s linear all', + event: 'enter', + structural: true + }; + + var animator = $animateCss(element, options); + + animator.start(); + triggerAnimationStartFrame(); + + + var style = element.attr('style'); + expect(element.css('transition-duration')).toMatch('5.5s'); + expect(element.css('transition-property')).toMatch('all'); + expect(style).toContain('linear'); + + expect(element).toHaveClass('ng-enter'); + expect(element).toHaveClass('ng-enter-active'); + + browserTrigger(element, 'transitionend', + { timeStamp: Date.now() + 10000, elapsedTime: 5.5 }); + + expect(element).not.toHaveClass('ng-enter'); + expect(element).not.toHaveClass('ng-enter-active'); + + expect(element.attr('style')).toBeFalsy(); + })); + + it("should give priority to the provided duration value, but only update the duration style itself", + inject(function($animateCss, $rootElement) { + + var options = { + transitionStyle: '5.5s ease-in color', + duration: 4, + event: 'enter', + structural: true + }; + + var animator = $animateCss(element, options); + + animator.start(); + triggerAnimationStartFrame(); + + var style = element.attr('style'); + expect(element.css('transition-duration')).toMatch('4s'); + expect(element.css('transition-property')).toMatch('color'); + expect(style).toContain('ease-in'); + })); + + it("should give priority to the provided delay value, but only update the delay style itself", + inject(function($animateCss, $rootElement) { + + var options = { + transitionStyle: '5.5s 4s ease-in color', + delay: 20, + event: 'enter', + structural: true + }; + + var animator = $animateCss(element, options); + + animator.start(); + triggerAnimationStartFrame(); + + var style = element.attr('style'); + expect(element.css('transition-delay')).toMatch('20s'); + expect(element.css('transition-duration')).toMatch('5.5s'); + expect(element.css('transition-property')).toMatch('color'); + expect(style).toContain('ease-in'); + })); + }); + + describe("[keyframeStyle]", function() { + it("should apply the keyframe animation directly onto the element and animate accordingly", + inject(function($animateCss, $rootElement) { + + var options = { + keyframeStyle: 'my_animation 5.5s', + event: 'enter', + structural: true + }; + + var animator = $animateCss(element, options); + + animator.start(); + triggerAnimationStartFrame(); + + + var detectedStyle = element.attr('style'); + expect(detectedStyle).toContain('5.5s'); + expect(detectedStyle).toContain('my_animation'); + + expect(element).toHaveClass('ng-enter'); + expect(element).toHaveClass('ng-enter-active'); + + browserTrigger(element, 'animationend', + { timeStamp: Date.now() + 10000, elapsedTime: 5.5 }); + + expect(element).not.toHaveClass('ng-enter'); + expect(element).not.toHaveClass('ng-enter-active'); + + expect(element.attr('style')).toBeFalsy(); + })); + + it("should give priority to the provided duration value, but only update the duration style itself", + inject(function($animateCss, $rootElement) { + + var options = { + keyframeStyle: 'my_animation 5.5s', + duration: 50, + event: 'enter', + structural: true + }; + + var animator = $animateCss(element, options); + + animator.start(); + triggerAnimationStartFrame(); + + + var detectedStyle = element.attr('style'); + expect(detectedStyle).toContain('50s'); + expect(detectedStyle).toContain('my_animation'); + })); + + it("should give priority to the provided delay value, but only update the duration style itself", + inject(function($animateCss, $rootElement) { + + var options = { + keyframeStyle: 'my_animation 5.5s 10s', + delay: 50, + event: 'enter', + structural: true + }; + + var animator = $animateCss(element, options); + + animator.start(); + triggerAnimationStartFrame(); + + + expect(element.css(prefix + 'animation-delay')).toEqual('50s'); + expect(element.css(prefix + 'animation-duration')).toEqual('5.5s'); + expect(element.css(prefix + 'animation-name')).toEqual('my_animation'); + })); + }); + + describe("[from] and [to]", function() { + it("should apply from styles to an element during the preparation phase", + inject(function($animateCss, $rootElement) { + + var options = { + duration: 2.5, + event: 'enter', + structural: true, + from: { width: '50px' }, + to: { width: '100px' } + }; + + var animator = $animateCss(element, options); + expect(element.attr('style')).toMatch(/width:\s*50px/); + })); + + it("should apply to styles to an element during the animation phase", + inject(function($animateCss, $rootElement) { + + var options = { + duration: 2.5, + event: 'enter', + structural: true, + from: { width: '15px' }, + to: { width: '25px' } + }; + + var animator = $animateCss(element, options); + var runner = animator.start(); + triggerAnimationStartFrame(); + runner.end(); + + expect(element.css('width')).toBe('25px'); + })); + + it("should apply the union of from and to styles to the element if no animation is run", + inject(function($animateCss, $rootElement) { + + var options = { + event: 'enter', + structural: true, + from: { 'width': '10px', height: '50px' }, + to: { 'width': '15px' } + }; + + var animator = $animateCss(element, options); + + expect(animator).toBeFalsy(); + expect(element.css('width')).toBe('15px'); + expect(element.css('height')).toBe('50px'); + })); + + it("should retain to and from styles on an element after an animation completes", + inject(function($animateCss, $rootElement) { + + var options = { + event: 'enter', + structural: true, + duration: 10, + from: { 'width': '10px', height: '66px' }, + to: { 'width': '5px' } + }; + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + browserTrigger(element, 'transitionend', + { timeStamp: Date.now() + 10000, elapsedTime: 10 }); + + expect(element).not.toHaveClass('ng-enter'); + expect(element.css('width')).toBe('5px'); + expect(element.css('height')).toBe('66px'); + })); + + it("should apply an inline transition if [to] styles and a duration are provided", + inject(function($animateCss, $rootElement) { + + var options = { + event: 'enter', + structural: true, + duration: 2.5, + to: { background: 'red' } + }; + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + var style = element.attr('style'); + expect(element.css('transition-duration')).toMatch('2.5s'); + expect(element.css('transition-property')).toMatch('all'); + expect(style).toContain('linear'); + })); + + it("should remove all inline transition styling when an animation completes", + inject(function($animateCss, $rootElement) { + + var options = { + event: 'enter', + structural: true, + duration: 2.5, + to: { background: 'red' } + }; + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + var style = element.attr('style'); + expect(style).toContain('transition'); + + browserTrigger(element, 'transitionend', + { timeStamp: Date.now() + 2500, elapsedTime: 2.5 }); + + style = element.attr('style'); + expect(style).not.toContain('transition'); + })); + + it("should retain existing styles when an inline styled animation completes", + inject(function($animateCss, $rootElement) { + + var options = { + event: 'enter', + structural: true, + duration: 2.5 + }; + + element.css('font-size', '20px'); + element.css('opacity', '0.5'); + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + var style = element.attr('style'); + expect(style).toContain('transition'); + animator.end(); + + style = element.attr('style'); + expect(element.attr('style')).not.toContain('transition'); + expect(element.css('opacity')).toEqual('0.5'); + })); + + it("should remove all inline transition delay styling when an animation completes", + inject(function($animateCss, $rootElement) { + + ss.addRule('.ng-enter', 'transition: 1s linear color'); + + var options = { + event: 'enter', + structural: true, + delay: 5 + }; + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + expect(element.css('transition-delay')).toEqual('5s'); + + browserTrigger(element, 'transitionend', + { timeStamp: Date.now() + 5000, elapsedTime: 1 }); + + expect(element.attr('style') || '').not.toContain('transition'); + })); + + it("should not apply an inline transition if only [from] styles and a duration are provided", + inject(function($animateCss, $rootElement) { + + var options = { + duration: 3, + from: { background: 'blue' } + }; + + var animator = $animateCss(element, options); + expect(animator).toBeFalsy(); + })); + + it("should apply a transition if [from] styles are provided with a class that is added", + inject(function($animateCss, $rootElement) { + + var options = { + addClass: 'superb', + from: { background: 'blue' } + }; + + var animator = $animateCss(element, options); + expect(isFunction(animator.start)).toBe(true); + })); + + it("should apply an inline transition if only [from] styles, but classes are added or removed and a duration is provided", + inject(function($animateCss, $rootElement) { + + var options = { + duration: 3, + addClass: 'sugar', + from: { background: 'yellow' } + }; + + var animator = $animateCss(element, options); + expect(animator).toBeTruthy(); + })); + + it("should not apply an inline transition if no styles are provided", + inject(function($animateCss, $rootElement) { + + var emptyObject = {}; + var options = { + duration: 3, + to: emptyObject, + from: emptyObject + }; + + var animator = $animateCss(element, options); + expect(animator).toBeFalsy(); + })); + + it("should apply a transition duration if the existing transition duration's property value is not 'all'", + inject(function($animateCss, $rootElement) { + + ss.addRule('.ng-enter', 'transition: 1s linear color'); + + var emptyObject = {}; + var options = { + event: 'enter', + structural: true, + to: { background: 'blue' } + }; + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + var style = element.attr('style'); + expect(element.css('transition-duration')).toMatch('1s'); + expect(element.css('transition-property')).toMatch('all'); + expect(style).toContain('linear'); + })); + + it("should apply a transition duration and an animation duration if duration + styles options are provided for a matching keyframe animation", + inject(function($animateCss, $rootElement) { + + ss.addRule('.ng-enter', '-webkit-animation:3.5s keyframe_animation;' + + 'animation:3.5s keyframe_animation;'); + + var emptyObject = {}; + var options = { + event: 'enter', + structural: true, + duration: 10, + to: { + background: 'blue' + } + }; + + var animator = $animateCss(element, options); + animator.start(); + triggerAnimationStartFrame(); + + + expect(element.css('transition-duration')).toMatch('10s'); + expect(element.css(prefix + 'animation-duration')).toEqual('10s'); + })); + }); + + describe("[easing]", function() { + + var element; + beforeEach(inject(function($document, $rootElement) { + element = jqLite('
'); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + })); + + it("should apply easing to a transition animation if it exists", inject(function($animateCss) { + ss.addRule('.red', 'transition:1s linear all;'); + var easing = 'ease-out'; + var animator = $animateCss(element, { addClass: 'red', easing: easing }); + animator.start(); + triggerAnimationStartFrame(); + + var style = element.attr('style'); + expect(style).toContain('ease-out'); + })); + + it("should not apply easing to transitions nor keyframes on an element animation if nothing is detected", + inject(function($animateCss) { + + ss.addRule('.red', ';'); + var easing = 'ease-out'; + var animator = $animateCss(element, { addClass: 'red', easing: easing }); + animator.start(); + triggerAnimationStartFrame(); + + expect(element.attr('style')).toBeFalsy(); + })); + + it("should apply easing to both keyframes and transition animations if detected", + inject(function($animateCss) { + + ss.addRule('.red', 'transition: 1s linear all;'); + ss.addRule('.blue', prefix + 'animation:my_keyframe 1s;'); + var easing = 'ease-out'; + var animator = $animateCss(element, { addClass: 'red blue', easing: easing }); + animator.start(); + triggerAnimationStartFrame(); + + var style = element.attr('style'); + expect(style).toMatch(/animation(?:-timing-function)?:\s*ease-out/); + expect(style).toMatch(/transition(?:-timing-function)?:\s*ease-out/); + })); + }); + + it('should round up long elapsedTime values to close off a CSS3 animation', + inject(function($animateCss) { + + ss.addRule('.millisecond-transition.ng-leave', '-webkit-transition:510ms linear all;' + + 'transition:510ms linear all;'); + + element.addClass('millisecond-transition'); + var animator = $animateCss(element, { + event: 'leave', + structural: true + }); + + animator.start(); + triggerAnimationStartFrame(); + + expect(element).toHaveClass('ng-leave-active'); + + browserTrigger(element, 'transitionend', + { timeStamp: Date.now() + 1000, elapsedTime: 0.50999999991 }); + + expect(element).not.toHaveClass('ng-leave-active'); + })); + }); + + describe('SVG', function() { + it('should properly apply transitions on an SVG element', + inject(function($animateCss, $rootScope, $compile, $document, $rootElement) { + + var element = $compile('' + + '' + + '')($rootScope); + + jqLite($document[0].body).append($rootElement); + $rootElement.append(element); + + $animateCss(element, { + event: 'enter', + structural: true, + duration: 10 + }).start(); + + triggerAnimationStartFrame(); + + expect(jqLiteHasClass(element[0], 'ng-enter')).toBe(true); + expect(jqLiteHasClass(element[0], 'ng-enter-active')).toBe(true); + + browserTrigger(element, 'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 10 }); + + expect(jqLiteHasClass(element[0], 'ng-enter')).toBe(false); + expect(jqLiteHasClass(element[0], 'ng-enter-active')).toBe(false); + })); + + it('should properly remove classes from SVG elements', inject(function($animateCss) { + var element = jqLite('' + + '' + + ''); + var child = element.find('rect'); + + $animateCss(child, { + removeClass: 'class-of-doom', + duration: 0 + }); + + expect(child.attr('class')).toBe(''); + })); + }); + }); +}); diff --git a/test/ngAnimate/animateJsDriverSpec.js b/test/ngAnimate/animateJsDriverSpec.js new file mode 100644 index 000000000000..274457965f10 --- /dev/null +++ b/test/ngAnimate/animateJsDriverSpec.js @@ -0,0 +1,178 @@ +'use strict'; + +describe("ngAnimate $$animateJsDriver", function() { + + beforeEach(module('ngAnimate')); + + it('should register the $$animateJsDriver into the list of drivers found in $animateProvider', + module(function($animateProvider) { + + expect($animateProvider.drivers).toContain('$$animateJsDriver'); + })); + + describe('with $$animateJs', function() { + var capturedAnimation = null; + var captureLog = []; + var element; + var driver; + + beforeEach(module(function($provide) { + $provide.factory('$$animateJs', function($$AnimateRunner) { + return function() { + var runner = new $$AnimateRunner(); + capturedAnimation = arguments; + captureLog.push({ + args: capturedAnimation, + runner: runner + }); + return { + start: function() { + return runner; + } + }; + }; + }); + + captureLog.length = 0; + element = jqLite('
'); + element.append(child1); + var child2 = jqLite('
'); + element.append(child2); + + driver({ + from: { + structural: true, + element: child1, + event: 'leave' + }, + to: { + structural: true, + element: child2, + event: 'enter' + } + }); + $rootScope.$digest(); + + expect(captureLog.length).toBe(2); + + var first = captureLog[0].args; + expect(first[0]).toBe(child1); + expect(first[1]).toBe('leave'); + + var second = captureLog[1].args; + expect(second[0]).toBe(child2); + expect(second[1]).toBe('enter'); + })); + + they('should $prop both animations when $prop() is called on the runner', ['end', 'cancel'], function(method) { + inject(function($rootScope, $$rAF) { + var child1 = jqLite('
'); + element.append(child1); + var child2 = jqLite('
'); + element.append(child2); + + var animator = driver({ + from: { + structural: true, + element: child1, + event: 'leave' + }, + to: { + structural: true, + element: child2, + event: 'enter' + } + }); + + var runner = animator.start(); + + var animationsClosed = false; + var status; + runner.done(function(s) { + animationsClosed = true; + status = s; + }); + + $rootScope.$digest(); + + runner[method](); + $$rAF.flush(); + + expect(animationsClosed).toBe(true); + expect(status).toBe(method === 'end' ? true : false); + }); + }); + + they('should fully $prop when all inner animations are complete', ['end', 'cancel'], function(method) { + inject(function($rootScope, $$rAF) { + var child1 = jqLite('
'); + element.append(child1); + var child2 = jqLite('
'); + element.append(child2); + + var animator = driver({ + from: { + structural: true, + element: child1, + event: 'leave' + }, + to: { + structural: true, + element: child2, + event: 'enter' + } + }); + + var runner = animator.start(); + + var animationsClosed = false; + var status; + runner.done(function(s) { + animationsClosed = true; + status = s; + }); + + $$rAF.flush(); + + captureLog[0].runner[method](); + expect(animationsClosed).toBe(false); + + captureLog[1].runner[method](); + expect(animationsClosed).toBe(true); + + expect(status).toBe(method === 'end' ? true : false); + }); + }); + }); +}); diff --git a/test/ngAnimate/animateJsSpec.js b/test/ngAnimate/animateJsSpec.js new file mode 100644 index 000000000000..63245b28e78d --- /dev/null +++ b/test/ngAnimate/animateJsSpec.js @@ -0,0 +1,672 @@ +'use strict'; + +describe("ngAnimate $$animateJs", function() { + + beforeEach(module('ngAnimate')); + + function getDoneFunction(args) { + for (var i = 1; i < args.length; i++) { + var a = args[i]; + if (isFunction(a)) return a; + } + } + + it('should return nothing if no animations are registered at all', inject(function($$animateJs) { + var element = jqLite('
'); + expect($$animateJs(element, 'enter')).toBeFalsy(); + })); + + it('should return nothing if no matching animations classes are found', function() { + module(function($animateProvider) { + $animateProvider.register('.foo', function() { + return { enter: noop }; + }); + }); + inject(function($$animateJs) { + var element = jqLite('
'); + expect($$animateJs(element, 'enter')).toBeFalsy(); + }); + }); + + it('should return nothing if a matching animation class is found, but not a matching event', function() { + module(function($animateProvider) { + $animateProvider.register('.foo', function() { + return { enter: noop }; + }); + }); + inject(function($$animateJs) { + var element = jqLite('
'); + expect($$animateJs(element, 'leave')).toBeFalsy(); + }); + }); + + it('should return a truthy value if a matching animation class and event are found', function() { + module(function($animateProvider) { + $animateProvider.register('.foo', function() { + return { enter: noop }; + }); + }); + inject(function($$animateJs) { + var element = jqLite('
'); + expect($$animateJs(element, 'enter')).toBeTruthy(); + }); + }); + + it('should strictly query for the animation based on the classes value if passed in', function() { + module(function($animateProvider) { + $animateProvider.register('.superman', function() { + return { enter: noop }; + }); + $animateProvider.register('.batman', function() { + return { leave: noop }; + }); + }); + inject(function($$animateJs) { + var element = jqLite('
'); + expect($$animateJs(element, 'enter', 'superman')).toBeTruthy(); + expect($$animateJs(element, 'leave', 'legoman batman')).toBeTruthy(); + expect($$animateJs(element, 'enter', 'legoman')).toBeFalsy(); + expect($$animateJs(element, 'leave', {})).toBeTruthy(); + }); + }); + + it('should run multiple animations in parallel', function() { + var doneCallbacks = []; + function makeAnimation(event) { + return function() { + var data = {}; + data[event] = function(element, done) { + doneCallbacks.push(done); + }; + return data; + }; + } + module(function($animateProvider) { + $animateProvider.register('.one', makeAnimation('enter')); + $animateProvider.register('.two', makeAnimation('enter')); + $animateProvider.register('.three', makeAnimation('enter')); + }); + inject(function($$animateJs, $$rAF) { + var element = jqLite('
'); + var animator = $$animateJs(element, 'enter'); + var complete = false; + animator.start().done(function() { + complete = true; + }); + expect(doneCallbacks.length).toBe(3); + forEach(doneCallbacks, function(cb) { + cb(); + }); + $$rAF.flush(); + expect(complete).toBe(true); + }); + }); + + they('should $prop the animation when runner.$prop() is called', ['end', 'cancel'], function(method) { + var ended = false; + var status; + module(function($animateProvider) { + $animateProvider.register('.the-end', function() { + return { + enter: function() { + return function(cancelled) { + ended = true; + status = cancelled ? 'cancel' : 'end'; + }; + } + }; + }); + }); + inject(function($$animateJs) { + var element = jqLite('
'); + var animator = $$animateJs(element, 'enter'); + var runner = animator.start(); + + expect(isFunction(runner[method])).toBe(true); + + expect(ended).toBeFalsy(); + runner[method](); + expect(ended).toBeTruthy(); + expect(status).toBe(method); + }); + }); + + they('should $prop all of the running the animations when runner.$prop() is called', + ['end', 'cancel'], function(method) { + + var lookup = {}; + module(function($animateProvider) { + forEach(['one','two','three'], function(klass) { + $animateProvider.register('.' + klass, function() { + return { + enter: function() { + return function(cancelled) { + lookup[klass] = cancelled ? 'cancel' : 'end'; + }; + } + }; + }); + }); + }); + inject(function($$animateJs) { + var element = jqLite('
'); + var animator = $$animateJs(element, 'enter'); + var runner = animator.start(); + + runner[method](); + expect(lookup.one).toBe(method); + expect(lookup.two).toBe(method); + expect(lookup.three).toBe(method); + }); + }); + + they('should only run the $prop operation once', ['end', 'cancel'], function(method) { + var ended = false; + var count = 0; + module(function($animateProvider) { + $animateProvider.register('.the-end', function() { + return { + enter: function() { + return function(cancelled) { + ended = true; + count++; + }; + } + }; + }); + }); + inject(function($$animateJs) { + var element = jqLite('
'); + var animator = $$animateJs(element, 'enter'); + var runner = animator.start(); + + expect(isFunction(runner[method])).toBe(true); + + expect(ended).toBeFalsy(); + runner[method](); + expect(ended).toBeTruthy(); + expect(count).toBe(1); + + runner[method](); + expect(count).toBe(1); + }); + }); + + it('should always run the provided animation in atleast one RAF frame if defined', function() { + var before, after, endCalled; + module(function($animateProvider) { + $animateProvider.register('.the-end', function() { + return { + beforeAddClass: function(element, className, done) { + before = done; + }, + addClass: function(element, className, done) { + after = done; + } + }; + }); + }); + inject(function($$animateJs, $$rAF) { + var element = jqLite('
'); + var animator = $$animateJs(element, 'addClass', { + addClass: 'red' + }); + + var runner = animator.start(); + runner.done(function() { + endCalled = true; + }); + + expect(before).toBeDefined(); + before(); + + expect(after).toBeUndefined(); + $$rAF.flush(); + expect(after).toBeDefined(); + after(); + + expect(endCalled).toBeUndefined(); + $$rAF.flush(); + expect(endCalled).toBe(true); + }); + }); + + they('should still run the associated DOM event when the $prop function is run but no more animations', ['cancel', 'end'], function(method) { + var log = []; + module(function($animateProvider) { + $animateProvider.register('.the-end', function() { + return { + beforeAddClass: function() { + return function(cancelled) { + var status = cancelled ? 'cancel' : 'end'; + log.push('before addClass ' + status); + }; + }, + addClass: function() { + return function(cancelled) { + var status = cancelled ? 'cancel' : 'end'; + log.push('after addClass' + status); + }; + } + }; + }); + }); + inject(function($$animateJs, $$rAF) { + var element = jqLite('
'); + var animator = $$animateJs(element, 'addClass', { + domOperation: function() { + log.push('dom addClass'); + } + }); + var runner = animator.start(); + runner.done(function() { + log.push('addClass complete'); + }); + runner[method](); + + $$rAF.flush(); + expect(log).toEqual( + ['before addClass ' + method, + 'dom addClass', + 'addClass complete']); + }); + }); + + it('should resolve the promise when end() is called', function() { + module(function($animateProvider) { + $animateProvider.register('.the-end', function() { + return { beforeAddClass: noop }; + }); + }); + inject(function($$animateJs, $$rAF, $rootScope) { + var element = jqLite('
'); + var animator = $$animateJs(element, 'addClass'); + var runner = animator.start(); + var done = false; + var cancelled = false; + runner.then(function() { + done = true; + }, function() { + cancelled = true; + }); + + runner.end(); + $$rAF.flush(); + $rootScope.$digest(); + expect(done).toBe(true); + expect(cancelled).toBe(false); + }); + }); + + it('should reject the promise when cancel() is called', function() { + module(function($animateProvider) { + $animateProvider.register('.the-end', function() { + return { beforeAddClass: noop }; + }); + }); + inject(function($$animateJs, $$rAF, $rootScope) { + var element = jqLite('
'); + var animator = $$animateJs(element, 'addClass'); + var runner = animator.start(); + var done = false; + var cancelled = false; + runner.then(function() { + done = true; + }, function() { + cancelled = true; + }); + + runner.cancel(); + $$rAF.flush(); + $rootScope.$digest(); + expect(done).toBe(false); + expect(cancelled).toBe(true); + }); + }); + + describe("events", function() { + var animations, runAnimation, element, log; + beforeEach(module(function($animateProvider) { + element = jqLite('
'); + animations = {}; + log = []; + + $animateProvider.register('.test-animation', function() { + return animations; + }); + + return function($$animateJs) { + runAnimation = function(method, done, error, options) { + options = extend(options || {}, { + domOperation: function() { + log.push('dom ' + method); + } + }); + + var driver = $$animateJs(element, method, 'test-animation', options); + driver.start().done(function(status) { + ((status ? done : error) || noop)(); + }); + }; + }; + })); + + they("$prop should have the function signature of (element, done, options) for the after animation", + ['enter', 'move', 'leave'], function(event) { + inject(function() { + var args; + var animationOptions = {}; + animationOptions.foo = 'bar'; + animations[event] = function() { + args = arguments; + }; + runAnimation(event, noop, noop, animationOptions); + + expect(args.length).toBe(3); + expect(args[0]).toBe(element); + expect(isFunction(args[1])).toBe(true); + expect(args[2].foo).toBe(animationOptions.foo); + }); + }); + + they("$prop should not execute a before function", enterMoveEvents, function(event) { + inject(function() { + var args; + var beforeMethod = 'before' + event.charAt(0).toUpperCase() + event.substr(1); + var animationOptions = {}; + animations[beforeMethod] = function() { + args = arguments; + }; + + runAnimation(event, noop, noop, animationOptions); + expect(args).toBeFalsy(); + }); + }); + + they("$prop should have the function signature of (element, className, done, options) for the before animation", + ['addClass', 'removeClass'], function(event) { + inject(function() { + var beforeMethod = 'before' + event.charAt(0).toUpperCase() + event.substr(1); + var args; + var className = 'matias'; + animations[beforeMethod] = function() { + args = arguments; + }; + + var animationOptions = {}; + animationOptions.foo = 'bar'; + animationOptions[event] = className; + runAnimation(event, noop, noop, animationOptions); + + expect(args.length).toBe(4); + expect(args[0]).toBe(element); + expect(args[1]).toBe(className); + expect(isFunction(args[2])).toBe(true); + expect(args[3].foo).toBe(animationOptions.foo); + }); + }); + + they("$prop should have the function signature of (element, className, done, options) for the after animation", + ['addClass', 'removeClass'], function(event) { + inject(function() { + var args; + var className = 'fatias'; + animations[event] = function() { + args = arguments; + }; + + var animationOptions = {}; + animationOptions.foo = 'bar'; + animationOptions[event] = className; + runAnimation(event, noop, noop, animationOptions); + + expect(args.length).toBe(4); + expect(args[0]).toBe(element); + expect(args[1]).toBe(className); + expect(isFunction(args[2])).toBe(true); + expect(args[3].foo).toBe(animationOptions.foo); + }); + }); + + they("setClass should have the function signature of (element, addClass, removeClass, done, options) for the $prop animation", ['before', 'after'], function(event) { + inject(function() { + var args; + var method = event === 'before' ? 'beforeSetClass' : 'setClass'; + animations[method] = function() { + args = arguments; + }; + + var addClass = 'on'; + var removeClass = 'on'; + var animationOptions = { + foo: 'bar', + addClass: addClass, + removeClass: removeClass + }; + runAnimation('setClass', noop, noop, animationOptions); + + expect(args.length).toBe(5); + expect(args[0]).toBe(element); + expect(args[1]).toBe(addClass); + expect(args[2]).toBe(removeClass); + expect(isFunction(args[3])).toBe(true); + expect(args[4].foo).toBe(animationOptions.foo); + }); + }); + + they("animate should have the function signature of (element, from, to, done, options) for the $prop animation", ['before', 'after'], function(event) { + inject(function() { + var args; + var method = event === 'before' ? 'beforeAnimate' : 'animate'; + animations[method] = function() { + args = arguments; + }; + + var to = { color: 'red' }; + var from = { color: 'blue' }; + var animationOptions = { + foo: 'bar', + to: to, + from: from + }; + runAnimation('animate', noop, noop, animationOptions); + + expect(args.length).toBe(5); + expect(args[0]).toBe(element); + expect(args[1]).toBe(from); + expect(args[2]).toBe(to); + expect(isFunction(args[3])).toBe(true); + expect(args[4].foo).toBe(animationOptions.foo); + }); + }); + + they("custom events should have the function signature of (element, done, options) for the $prop animation", ['before', 'after'], function(event) { + inject(function() { + var args; + var method = event === 'before' ? 'beforeCustom' : 'custom'; + animations[method] = function() { + args = arguments; + }; + + var animationOptions = {}; + animationOptions.foo = 'bar'; + runAnimation('custom', noop, noop, animationOptions); + + expect(args.length).toBe(3); + expect(args[0]).toBe(element); + expect(isFunction(args[1])).toBe(true); + expect(args[2].foo).toBe(animationOptions.foo); + }); + }); + + var enterMoveEvents = ['enter', 'move']; + var otherEvents = ['addClass', 'removeClass', 'setClass']; + var allEvents = ['leave'].concat(otherEvents).concat(enterMoveEvents); + + they("$prop should asynchronously render the before$prop animation", otherEvents, function(event) { + inject(function($$rAF) { + var beforeMethod = 'before' + event.charAt(0).toUpperCase() + event.substr(1); + animations[beforeMethod] = function(element, a, b, c) { + log.push('before ' + event); + var done = getDoneFunction(arguments); + done(); + }; + + runAnimation(event); + expect(log).toEqual(['before ' + event]); + $$rAF.flush(); + + expect(log).toEqual(['before ' + event, 'dom ' + event]); + }); + }); + + they("$prop should asynchronously render the $prop animation", allEvents, function(event) { + inject(function($$rAF) { + animations[event] = function(element, a, b, c) { + log.push('after ' + event); + var done = getDoneFunction(arguments); + done(); + }; + + runAnimation(event, function() { + log.push('complete'); + }); + + if (event === 'leave') { + expect(log).toEqual(['after leave']); + $$rAF.flush(); + expect(log).toEqual(['after leave', 'dom leave', 'complete']); + } else { + expect(log).toEqual(['dom ' + event, 'after ' + event]); + $$rAF.flush(); + expect(log).toEqual(['dom ' + event, 'after ' + event, 'complete']); + } + }); + }); + + they("$prop should asynchronously reject the before animation if the callback function is called with false", otherEvents, function(event) { + inject(function($$rAF, $rootScope) { + var beforeMethod = 'before' + event.charAt(0).toUpperCase() + event.substr(1); + animations[beforeMethod] = function(element, a, b, c) { + log.push('before ' + event); + var done = getDoneFunction(arguments); + done(false); + }; + + animations[event] = function(element, a, b, c) { + log.push('after ' + event); + var done = getDoneFunction(arguments); + done(); + }; + + runAnimation(event, + function() { log.push('pass'); }, + function() { log.push('fail'); }); + + expect(log).toEqual(['before ' + event]); + $$rAF.flush(); + expect(log).toEqual(['before ' + event, 'dom ' + event, 'fail']); + }); + }); + + they("$prop should asynchronously reject the after animation if the callback function is called with false", allEvents, function(event) { + inject(function($$rAF, $rootScope) { + animations[event] = function(element, a, b, c) { + log.push('after ' + event); + var done = getDoneFunction(arguments); + done(false); + }; + + runAnimation(event, + function() { log.push('pass'); }, + function() { log.push('fail'); }); + + var expectations = []; + if (event === 'leave') { + expect(log).toEqual(['after leave']); + $$rAF.flush(); + expect(log).toEqual(['after leave', 'dom leave', 'fail']); + } else { + expect(log).toEqual(['dom ' + event, 'after ' + event]); + $$rAF.flush(); + expect(log).toEqual(['dom ' + event, 'after ' + event, 'fail']); + } + }); + }); + + it('setClass should delegate down to addClass/removeClass if not defined', inject(function($$rAF) { + animations.addClass = function(element, done) { + log.push('addClass'); + }; + + animations.removeClass = function(element, done) { + log.push('removeClass'); + }; + + expect(animations.setClass).toBeFalsy(); + + runAnimation('setClass'); + + expect(log).toEqual(['dom setClass', 'removeClass', 'addClass']); + })); + + it('beforeSetClass should delegate down to beforeAddClass/beforeRemoveClass if not defined', + inject(function($$rAF) { + + animations.beforeAddClass = function(element, className, done) { + log.push('beforeAddClass'); + done(); + }; + + animations.beforeRemoveClass = function(element, className, done) { + log.push('beforeRemoveClass'); + done(); + }; + + expect(animations.setClass).toBeFalsy(); + + runAnimation('setClass'); + $$rAF.flush(); + + expect(log).toEqual(['beforeRemoveClass', 'beforeAddClass', 'dom setClass']); + })); + + it('leave should always ignore the `beforeLeave` animation', + inject(function($$rAF) { + + animations.beforeLeave = function(element, done) { + log.push('beforeLeave'); + done(); + }; + + animations.leave = function(element, done) { + log.push('leave'); + done(); + }; + + runAnimation('leave'); + $$rAF.flush(); + + expect(log).toEqual(['leave', 'dom leave']); + })); + + it('should allow custom events to be triggered', + inject(function($$rAF) { + + animations.beforeFlex = function(element, done) { + log.push('beforeFlex'); + done(); + }; + + animations.flex = function(element, done) { + log.push('flex'); + done(); + }; + + runAnimation('flex'); + $$rAF.flush(); + + expect(log).toEqual(['beforeFlex', 'dom flex', 'flex']); + })); + }); +}); diff --git a/test/ngAnimate/animateRunnerSpec.js b/test/ngAnimate/animateRunnerSpec.js new file mode 100644 index 000000000000..94178fba6189 --- /dev/null +++ b/test/ngAnimate/animateRunnerSpec.js @@ -0,0 +1,340 @@ +'use strict'; + +describe('$$rAFMutex', function() { + beforeEach(module('ngAnimate')); + + it('should fire the callback only when one or more RAFs have passed', + inject(function($$rAF, $$rAFMutex) { + + var trigger = $$rAFMutex(); + var called = false; + trigger(function() { + called = true; + }); + + expect(called).toBe(false); + $$rAF.flush(); + expect(called).toBe(true); + })); + + it('should immediately fire the callback if a RAF has passed since construction', + inject(function($$rAF, $$rAFMutex) { + + var trigger = $$rAFMutex(); + $$rAF.flush(); + + var called = false; + trigger(function() { + called = true; + }); + expect(called).toBe(true); + })); +}); + +describe("$$AnimateRunner", function() { + + beforeEach(module('ngAnimate')); + + they("should trigger the host $prop function", + ['end', 'cancel', 'pause', 'resume'], function(method) { + + inject(function($$AnimateRunner) { + var host = {}; + var spy = host[method] = jasmine.createSpy(); + var runner = new $$AnimateRunner(host); + runner[method](); + expect(spy).toHaveBeenCalled(); + }); + }); + + they("should trigger the inner runner's host $prop function", + ['end', 'cancel', 'pause', 'resume'], function(method) { + + inject(function($$AnimateRunner) { + var host = {}; + var spy = host[method] = jasmine.createSpy(); + var runner1 = new $$AnimateRunner(); + var runner2 = new $$AnimateRunner(host); + runner1.setHost(runner2); + runner1[method](); + expect(spy).toHaveBeenCalled(); + }); + }); + + it("should resolve the done function only if one RAF has passed", + inject(function($$AnimateRunner, $$rAF) { + + var runner = new $$AnimateRunner(); + var spy = jasmine.createSpy(); + runner.done(spy); + runner.complete(true); + expect(spy).not.toHaveBeenCalled(); + $$rAF.flush(); + expect(spy).toHaveBeenCalled(); + })); + + it("should resolve with the status provided in the completion function", + inject(function($$AnimateRunner, $$rAF) { + + var runner = new $$AnimateRunner(); + var capturedValue; + runner.done(function(val) { + capturedValue = val; + }); + runner.complete('special value'); + $$rAF.flush(); + expect(capturedValue).toBe('special value'); + })); + + they("should immediately resolve each combined runner in a bottom-up order when $prop is called", + ['end', 'cancel'], function(method) { + + inject(function($$AnimateRunner, $$rAF) { + var runner1 = new $$AnimateRunner(); + var runner2 = new $$AnimateRunner(); + runner1.setHost(runner2); + + var status1, status2, signature = ''; + runner1.done(function(status) { + signature += '1'; + status1 = status; + }); + + runner2.done(function(status) { + signature += '2'; + status2 = status; + }); + + runner1[method](); + + var expectedStatus = method === 'end' ? true : false; + expect(status1).toBe(expectedStatus); + expect(status2).toBe(expectedStatus); + expect(signature).toBe('21'); + }); + }); + + they("should resolve/reject using a newly created promise when .then() is used upon $prop", + ['end', 'cancel'], function(method) { + + inject(function($$AnimateRunner, $rootScope) { + var runner1 = new $$AnimateRunner(); + var runner2 = new $$AnimateRunner(); + runner1.setHost(runner2); + + var status1; + runner1.then( + function() { status1 = 'pass'; }, + function() { status1 = 'fail'; }); + + var status2; + runner2.then( + function() { status2 = 'pass'; }, + function() { status2 = 'fail'; }); + + runner1[method](); + + var expectedStatus = method === 'end' ? 'pass' : 'fail'; + + expect(status1).toBeUndefined(); + expect(status2).toBeUndefined(); + + $rootScope.$digest(); + expect(status1).toBe(expectedStatus); + expect(status2).toBe(expectedStatus); + }); + }); + + it("should expose/create the contained promise when getPromise() is called", + inject(function($$AnimateRunner, $rootScope) { + + var runner = new $$AnimateRunner(); + expect(isPromiseLike(runner.getPromise())).toBeTruthy(); + })); + + it("should expose the `catch` promise function to handle the rejected state", + inject(function($$AnimateRunner, $rootScope) { + + var runner = new $$AnimateRunner(); + var animationFailed = false; + runner.catch(function() { + animationFailed = true; + }); + runner.cancel(); + $rootScope.$digest(); + expect(animationFailed).toBe(true); + })); + + they("should expose the `finally` promise function to handle the final state when $prop", + { 'rejected': 'cancel', 'resolved': 'end' }, function(method) { + inject(function($$AnimateRunner, $rootScope) { + var runner = new $$AnimateRunner(); + var animationComplete = false; + runner.finally(function() { + animationComplete = true; + }); + runner[method](); + $rootScope.$digest(); + expect(animationComplete).toBe(true); + }); + }); + + describe(".all()", function() { + it("should resolve when all runners have naturally resolved", + inject(function($$rAF, $$AnimateRunner) { + + var runner1 = new $$AnimateRunner(); + var runner2 = new $$AnimateRunner(); + var runner3 = new $$AnimateRunner(); + + var status; + $$AnimateRunner.all([runner1, runner2, runner3], function(response) { + status = response; + }); + + runner1.complete(true); + runner2.complete(true); + runner3.complete(true); + + expect(status).toBeUndefined(); + + $$rAF.flush(); + + expect(status).toBe(true); + })); + + they("should immediately resolve if and when all runners have been $prop", + { ended: 'end', cancelled: 'cancel' }, function(method) { + + inject(function($$rAF, $$AnimateRunner) { + var runner1 = new $$AnimateRunner(); + var runner2 = new $$AnimateRunner(); + var runner3 = new $$AnimateRunner(); + + var expectedStatus = method === 'end' ? true : false; + + var status; + $$AnimateRunner.all([runner1, runner2, runner3], function(response) { + status = response; + }); + + runner1[method](); + runner2[method](); + runner3[method](); + + expect(status).toBe(expectedStatus); + }); + }); + + it("should return a status of `false` if one or more runners was cancelled", + inject(function($$rAF, $$AnimateRunner) { + + var runner1 = new $$AnimateRunner(); + var runner2 = new $$AnimateRunner(); + var runner3 = new $$AnimateRunner(); + + var status; + $$AnimateRunner.all([runner1, runner2, runner3], function(response) { + status = response; + }); + + runner1.end(); + runner2.end(); + runner3.cancel(); + + expect(status).toBe(false); + })); + }); + + describe(".chain()", function() { + it("should evaluate an array of functions in a chain", + inject(function($$rAF, $$AnimateRunner) { + + var runner1 = new $$AnimateRunner(); + var runner2 = new $$AnimateRunner(); + var runner3 = new $$AnimateRunner(); + + var log = []; + + var items = []; + items.push(function(fn) { + runner1.done(function() { + log.push(1); + fn(); + }); + }); + + items.push(function(fn) { + runner2.done(function() { + log.push(2); + fn(); + }); + }); + + items.push(function(fn) { + runner3.done(function() { + log.push(3); + fn(); + }); + }); + + var status; + $$AnimateRunner.chain(items, function(response) { + status = response; + }); + + $$rAF.flush(); + + runner2.complete(true); + expect(log).toEqual([]); + expect(status).toBeUndefined(); + + runner1.complete(true); + expect(log).toEqual([1,2]); + expect(status).toBeUndefined(); + + runner3.complete(true); + expect(log).toEqual([1,2,3]); + expect(status).toBe(true); + })); + + it("should break the chian when a function evaluates to false", + inject(function($$rAF, $$AnimateRunner) { + + var runner1 = new $$AnimateRunner(); + var runner2 = new $$AnimateRunner(); + var runner3 = new $$AnimateRunner(); + var runner4 = new $$AnimateRunner(); + var runner5 = new $$AnimateRunner(); + var runner6 = new $$AnimateRunner(); + + var log = []; + + var items = []; + items.push(function(fn) { log.push(1); runner1.done(fn); }); + items.push(function(fn) { log.push(2); runner2.done(fn); }); + items.push(function(fn) { log.push(3); runner3.done(fn); }); + items.push(function(fn) { log.push(4); runner4.done(fn); }); + items.push(function(fn) { log.push(5); runner5.done(fn); }); + items.push(function(fn) { log.push(6); runner6.done(fn); }); + + var status; + $$AnimateRunner.chain(items, function(response) { + status = response; + }); + + runner1.complete(''); + runner2.complete(null); + runner3.complete(undefined); + runner4.complete(0); + runner5.complete(false); + + runner6.complete(true); + + $$rAF.flush(); + + expect(log).toEqual([1,2,3,4,5]); + expect(status).toBe(false); + })); + }); +}); diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index be5a1b59e27e..5d89274585c4 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -1,5578 +1,1341 @@ 'use strict'; -describe("ngAnimate", function() { - var $originalAnimate; - beforeEach(module(function($provide) { - $provide.decorator('$animate', function($delegate) { - $originalAnimate = $delegate; - return $delegate; - }); - })); - beforeEach(module('ngAnimate')); - beforeEach(module('ngAnimateMock')); - - function getMaxValue(prop, element, $window) { - var node = element[0]; - var cs = $window.getComputedStyle(node); - var prop0 = 'webkit' + prop.charAt(0).toUpperCase() + prop.substr(1); - var values = (cs[prop0] || cs[prop]).split(/\s*,\s*/); - var maxDelay = 0; - forEach(values, function(value) { - maxDelay = Math.max(parseFloat(value) || 0, maxDelay); - }); - return maxDelay; - } - - it("should disable animations on bootstrap for structural animations even after the first digest has passed", function() { - var hasBeenAnimated = false; - module(function($animateProvider) { - $animateProvider.register('.my-structrual-animation', function() { - return { - enter: function(element, done) { - hasBeenAnimated = true; - done(); - }, - leave: function(element, done) { - hasBeenAnimated = true; - done(); - } - }; - }); - }); - inject(function($rootScope, $compile, $animate, $rootElement, $document) { - var element = $compile('
...
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); +describe("animations", function() { - $animate.enter(element, $rootElement); - $rootScope.$digest(); - - expect(hasBeenAnimated).toBe(false); + beforeEach(module('ngAnimate')); - $animate.leave(element); - $rootScope.$digest(); + var element, applyAnimationClasses; + afterEach(inject(function($$jqLite) { + applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + dealoc(element); + })); - expect(hasBeenAnimated).toBe(true); - }); - }); + describe('during bootstrap', function() { + it('should be enabled only after the first digest is fired and the postDigest queue is empty', + inject(function($animate, $rootScope) { - it("should disable animations for two digests until all pending HTTP requests are complete during bootstrap", function() { - var animateSpy = jasmine.createSpy(); - module(function($animateProvider, $compileProvider) { - $compileProvider.directive('myRemoteDirective', function() { - return { - templateUrl: 'remote.html' - }; - }); - $animateProvider.register('.my-structrual-animation', function() { - return { - enter: animateSpy, - leave: animateSpy - }; + var capturedEnabledState; + $rootScope.$$postDigest(function() { + capturedEnabledState = $animate.enabled(); }); - }); - inject(function($rootScope, $compile, $animate, $rootElement, $document, $httpBackend) { - - $httpBackend.whenGET('remote.html').respond(200, 'content'); - var element = $compile('
...
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - // running this twice just to prove that the dual post digest is run - $rootScope.$digest(); + expect($animate.enabled()).toBe(false); $rootScope.$digest(); - $animate.enter(element, $rootElement); - $rootScope.$digest(); + expect(capturedEnabledState).toBe(false); + expect($animate.enabled()).toBe(true); + })); - expect(animateSpy).not.toHaveBeenCalled(); + it('should be disabled until all pending template requests have been downloaded', function() { + var mockTemplateRequest = { + totalPendingRequests: 2 + }; - $httpBackend.flush(); - $rootScope.$digest(); + module(function($provide) { + $provide.value('$templateRequest', mockTemplateRequest); + }); + inject(function($animate, $rootScope) { + expect($animate.enabled()).toBe(false); - $animate.leave(element); - $rootScope.$digest(); + $rootScope.$digest(); + expect($animate.enabled()).toBe(false); - expect(animateSpy).toHaveBeenCalled(); + mockTemplateRequest.totalPendingRequests = 0; + $rootScope.$digest(); + expect($animate.enabled()).toBe(true); + }); }); - }); + it('should stay disabled if set to be disabled even after all templates have been fully downloaded', function() { + var mockTemplateRequest = { + totalPendingRequests: 2 + }; - //we use another describe block because the before/after operations below - //are used across all animations tests and we don't want that same behavior - //to be used on the root describe block at the start of the animateSpec.js file - describe('', function() { + module(function($provide) { + $provide.value('$templateRequest', mockTemplateRequest); + }); + inject(function($animate, $rootScope) { + $animate.enabled(false); + expect($animate.enabled()).toBe(false); - var ss, body; - beforeEach(module(function() { - body = jqLite(document.body); - return function($window, $document, $animate, $timeout, $rootScope) { - ss = createMockStyleSheet($document, $window); - try { - $timeout.flush(); - } catch (e) {} - $animate.enabled(true); $rootScope.$digest(); - }; - })); + expect($animate.enabled()).toBe(false); - afterEach(function() { - if (ss) { - ss.destroy(); - } - dealoc(body); + mockTemplateRequest.totalPendingRequests = 0; + $rootScope.$digest(); + expect($animate.enabled()).toBe(false); + }); }); + }); + describe('$animate', function() { + var parent; + var parent2; + var options; + var capturedAnimation; + var capturedAnimationHistory; + var overriddenAnimationRunner; + var defaultFakeAnimationRunner; - describe("$animate", function() { + beforeEach(module(function($provide) { + overriddenAnimationRunner = null; + capturedAnimation = null; + capturedAnimationHistory = []; - var element, $rootElement; + options = {}; + $provide.value('$$animation', function() { + capturedAnimationHistory.push(capturedAnimation = arguments); + return overriddenAnimationRunner || defaultFakeAnimationRunner; + }); - function html(content) { - body.append($rootElement); - $rootElement.html(content); - element = $rootElement.children().eq(0); - return element; - } + return function($document, $rootElement, $q, $animate, $$AnimateRunner) { + defaultFakeAnimationRunner = new $$AnimateRunner(); + $animate.enabled(true); - describe("enable / disable", function() { + element = jqLite('
element
'); + parent = jqLite('
parent
'); + parent2 = jqLite('
parent
'); - it("should work for all animations", inject(function($animate) { + $rootElement.append(parent); + $rootElement.append(parent2); + jqLite($document[0].body).append($rootElement); + }; + })); - expect($animate.enabled()).toBe(true); + it('should animate only the specified CSS className matched within $animateProvider.classNameFilter', function() { + module(function($animateProvider) { + $animateProvider.classNameFilter(/only-allow-this-animation/); + }); + inject(function($animate, $rootScope, $document, $rootElement) { + expect(element).not.toHaveClass('only-allow-this-animation'); - expect($animate.enabled(0)).toBe(false); - expect($animate.enabled()).toBe(false); + $animate.enter(element, parent); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); - expect($animate.enabled(1)).toBe(true); - expect($animate.enabled()).toBe(true); - })); + element.addClass('only-allow-this-animation'); + $animate.leave(element, parent); + $rootScope.$digest(); + expect(capturedAnimation).toBeTruthy(); + }); + }); - it('should place a hard disable on all child animations', function() { - var count = 0; - module(function($animateProvider) { - $animateProvider.register('.animated', function() { - return { - addClass: function(element, className, done) { - count++; - done(); - } - }; - }); - }); - inject(function($compile, $rootScope, $animate, $sniffer, $rootElement) { - $animate.enabled(true); + describe('enabled()', function() { + it("should work for all animations", inject(function($animate) { - var elm1 = $compile('
')($rootScope); - var elm2 = $compile('
')($rootScope); - $rootElement.append(elm1); - angular.element(document.body).append($rootElement); + expect($animate.enabled()).toBe(true); - $animate.addClass(elm1, 'klass'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(count).toBe(1); + expect($animate.enabled(0)).toBe(false); + expect($animate.enabled()).toBe(false); - $animate.enabled(false); + expect($animate.enabled(1)).toBe(true); + expect($animate.enabled()).toBe(true); + })); - $animate.addClass(elm1, 'klass2'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(count).toBe(1); + it('should fully disable all animations in the application if false', + inject(function($animate, $rootScope) { - $animate.enabled(true); + $animate.enabled(false); - elm1.append(elm2); + $animate.enter(element, parent); - $animate.addClass(elm2, 'klass'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(count).toBe(2); + expect(capturedAnimation).toBeFalsy(); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); + })); - $animate.enabled(false, elm1); + it('should disable all animations on the given element', + inject(function($animate, $rootScope) { - $animate.addClass(elm2, 'klass2'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(count).toBe(2); + parent.append(element); - var root = angular.element($rootElement[0]); - $rootElement.addClass('animated'); - $animate.addClass(root, 'klass2'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(count).toBe(3); - }); - }); + $animate.enabled(element, false); + expect($animate.enabled(element)).toBeFalsy(); + $animate.addClass(element, 'red'); + expect(capturedAnimation).toBeFalsy(); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); - it('should skip animations if the element is attached to the $rootElement', function() { - var count = 0; - module(function($animateProvider) { - $animateProvider.register('.animated', function() { - return { - addClass: function(element, className, done) { - count++; - done(); - } - }; - }); - }); - inject(function($compile, $rootScope, $animate) { - $animate.enabled(true); - - var elm1 = $compile('
')($rootScope); - - $animate.addClass(elm1, 'klass2'); - $rootScope.$digest(); - expect(count).toBe(0); - }); - }); + $animate.enabled(element, true); + expect($animate.enabled(element)).toBeTruthy(); + $animate.addClass(element, 'blue'); + expect(capturedAnimation).toBeFalsy(); + $rootScope.$digest(); + expect(capturedAnimation).toBeTruthy(); + })); - it('should check enable/disable animations up until the $rootElement element', function() { - var rootElm = jqLite('
'); - - var captured = false; - module(function($provide, $animateProvider) { - $provide.value('$rootElement', rootElm); - $animateProvider.register('.capture-animation', function() { - return { - addClass: function(element, className, done) { - captured = true; - done(); - } - }; - }); - }); - inject(function($animate, $rootElement, $rootScope, $compile) { - angular.bootstrap(rootElm, ['ngAnimate']); - - $animate.enabled(true); - - var element = $compile('
')($rootScope); - rootElm.append(element); - - expect(captured).toBe(false); - $animate.addClass(element, 'red'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(captured).toBe(true); - - captured = false; - $animate.enabled(false); - - $animate.addClass(element, 'blue'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(captured).toBe(false); - - //clean up the mess - $animate.enabled(false, rootElm); - dealoc(rootElm); - }); - }); - }); + it('should disable all animations for a given element\'s children', + inject(function($animate, $rootScope) { + $animate.enabled(parent, false); - describe("with polyfill", function() { - - var child, after; - - beforeEach(function() { - module(function($animateProvider) { - $animateProvider.register('.custom', function() { - return { - start: function(element, done) { - done(); - } - }; - }); - $animateProvider.register('.custom-delay', function($timeout) { - function animate(element, done) { - done = arguments.length == 4 ? arguments[2] : done; - $timeout(done, 2000, false); - return function() { - element.addClass('animation-cancelled'); - }; - } - return { - leave: animate, - addClass: animate, - removeClass: animate - }; - }); - $animateProvider.register('.custom-long-delay', function($timeout) { - function animate(element, done) { - done = arguments.length == 4 ? arguments[2] : done; - $timeout(done, 20000, false); - return function(cancelled) { - element.addClass(cancelled ? 'animation-cancelled' : 'animation-ended'); - }; - } - return { - leave: animate, - addClass: animate, - removeClass: animate - }; - }); - $animateProvider.register('.setup-memo', function() { - return { - removeClass: function(element, className, done) { - element.text('memento'); - done(); - } - }; - }); - return function($animate, $compile, $rootScope, $rootElement) { - element = $compile('
')($rootScope); - - forEach(['.ng-hide-add', '.ng-hide-remove', '.ng-enter', '.ng-leave', '.ng-move', '.my-inline-animation'], function(selector) { - ss.addRule(selector, '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); - }); - - child = $compile('
...
')($rootScope); - jqLite($document[0].body).append($rootElement); - element.append(child); - - after = $compile('
')($rootScope); - $rootElement.append(element); - }; - }); - }); + $animate.enter(element, parent); + expect(capturedAnimation).toBeFalsy(); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); + $animate.enabled(parent, true); - it("should animate the enter animation event", - inject(function($animate, $rootScope, $sniffer) { - element[0].removeChild(child[0]); + $animate.enter(element, parent); + expect(capturedAnimation).toBeFalsy(); + $rootScope.$digest(); + expect(capturedAnimation).toBeTruthy(); + })); + }); - expect(element.contents().length).toBe(0); - $animate.enter(child, element); - $rootScope.$digest(); + it('should strip all comment nodes from the animation and not issue an animation if not real elements are found', + inject(function($rootScope, $compile) { - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(child.hasClass('ng-enter')).toBe(true); - expect(child.hasClass('ng-enter-active')).toBe(true); - browserTrigger(element, 'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } + // since the ng-if results to false then only comments will be fed into the animation + element = $compile( + '
' + )($rootScope); - expect(element.contents().length).toBe(1); - })); + parent.append(element); - it("should animate the enter animation event with native dom elements", - inject(function($animate, $rootScope, $sniffer) { - element[0].removeChild(child[0]); + $rootScope.items = [1,2,3,4,5]; + $rootScope.$digest(); - expect(element.contents().length).toBe(0); - $animate.enter(child[0], element[0]); - $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); + })); - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(child.hasClass('ng-enter')).toBe(true); - expect(child.hasClass('ng-enter-active')).toBe(true); - browserTrigger(element, 'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } + it('enter() should issue an enter animation and fire the DOM operation right away before the animation kicks off', inject(function($animate, $rootScope) { + expect(parent.children().length).toBe(0); - expect(element.contents().length).toBe(1); - })); + options.foo = 'bar'; + $animate.enter(element, parent, null, options); + expect(parent.children().length).toBe(1); - it("should animate the leave animation event", - inject(function($animate, $rootScope, $sniffer) { + $rootScope.$digest(); - expect(element.contents().length).toBe(1); - $animate.leave(child); - $rootScope.$digest(); + expect(capturedAnimation[0]).toBe(element); + expect(capturedAnimation[1]).toBe('enter'); + expect(capturedAnimation[2].foo).toEqual(options.foo); + })); - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(child.hasClass('ng-leave')).toBe(true); - expect(child.hasClass('ng-leave-active')).toBe(true); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } + it('move() should issue an enter animation and fire the DOM operation right away before the animation kicks off', inject(function($animate, $rootScope) { + parent.append(element); - expect(element.contents().length).toBe(0); - })); + expect(parent.children().length).toBe(1); + expect(parent2.children().length).toBe(0); - it("should animate the leave animation event with native dom elements", - inject(function($animate, $rootScope, $sniffer) { + options.foo = 'bar'; + $animate.move(element, parent2, null, options); - expect(element.contents().length).toBe(1); - $animate.leave(child[0]); - $rootScope.$digest(); + expect(parent.children().length).toBe(0); + expect(parent2.children().length).toBe(1); - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(child.hasClass('ng-leave')).toBe(true); - expect(child.hasClass('ng-leave-active')).toBe(true); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } + $rootScope.$digest(); - expect(element.contents().length).toBe(0); - })); + expect(capturedAnimation[0]).toBe(element); + expect(capturedAnimation[1]).toBe('move'); + expect(capturedAnimation[2].foo).toEqual(options.foo); + })); - it("should animate the move animation event", - inject(function($animate, $compile, $rootScope, $timeout, $sniffer) { + they('$prop() should insert the element adjacent to the after element if provided', + ['enter', 'move'], function(event) { - $rootScope.$digest(); - element.empty(); - - var child1 = $compile('
1
')($rootScope); - var child2 = $compile('
2
')($rootScope); - element.append(child1); - element.append(child2); - expect(element.text()).toBe('12'); - $animate.move(child1, element, child2); - $rootScope.$digest(); - if ($sniffer.transitions) { - $animate.triggerReflow(); - } - expect(element.text()).toBe('21'); - })); + inject(function($animate, $rootScope) { + parent.append(element); + assertCompareNodes(parent2.next(), element, true); + $animate[event](element, null, parent2, options); + assertCompareNodes(parent2.next(), element); + $rootScope.$digest(); + expect(capturedAnimation[1]).toBe(event); + }); + }); - it("should animate the move animation event with native dom elements", - inject(function($animate, $compile, $rootScope, $timeout, $sniffer) { + they('$prop() should append to the parent incase the after element is destroyed before the DOM operation is issued', + ['enter', 'move'], function(event) { + inject(function($animate, $rootScope) { + parent2.remove(); + $animate[event](element, parent, parent2, options); + expect(parent2.next()).not.toEqual(element); + $rootScope.$digest(); + expect(capturedAnimation[1]).toBe(event); + }); + }); - $rootScope.$digest(); - element.empty(); - - var child1 = $compile('
1
')($rootScope); - var child2 = $compile('
2
')($rootScope); - element.append(child1); - element.append(child2); - expect(element.text()).toBe('12'); - $animate.move(child1[0], element[0], child2[0]); - $rootScope.$digest(); - if ($sniffer.transitions) { - $animate.triggerReflow(); - } - expect(element.text()).toBe('21'); - })); + it('leave() should issue a leave animation with the correct DOM operation', inject(function($animate, $rootScope) { + parent.append(element); + options.foo = 'bar'; + $animate.leave(element, options); + $rootScope.$digest(); - it("should perform the animate event", - inject(function($animate, $compile, $rootScope, $timeout, $sniffer) { + expect(capturedAnimation[0]).toBe(element); + expect(capturedAnimation[1]).toBe('leave'); + expect(capturedAnimation[2].foo).toEqual(options.foo); - $rootScope.$digest(); - $animate.animate(element, { color: 'rgb(255, 0, 0)' }, { color: 'rgb(0, 0, 255)' }, 'animated'); - $rootScope.$digest(); + expect(element.parent().length).toBe(1); + capturedAnimation[2].domOperation(); + expect(element.parent().length).toBe(0); + })); - if ($sniffer.transitions) { - expect(element.css('color')).toBe('rgb(255, 0, 0)'); - $animate.triggerReflow(); - } - expect(element.css('color')).toBe('rgb(0, 0, 255)'); - })); + it('should remove all element and comment nodes during leave animation', + inject(function($compile, $rootScope, $$rAF, $$AnimateRunner) { - it("should animate the show animation event", - inject(function($animate, $rootScope, $sniffer) { + element = $compile( + '
' + + '
start
' + + '
end
' + + '
' + )($rootScope); - $rootScope.$digest(); - child.addClass('ng-hide'); - expect(child).toBeHidden(); - $animate.removeClass(child, 'ng-hide'); - $rootScope.$digest(); - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(child.hasClass('ng-hide-remove')).toBe(true); - expect(child.hasClass('ng-hide-remove-active')).toBe(true); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } - expect(child.hasClass('ng-hide-remove')).toBe(false); - expect(child.hasClass('ng-hide-remove-active')).toBe(false); - expect(child).toBeShown(); - })); + parent.append(element); - it("should animate the hide animation event", - inject(function($animate, $rootScope, $sniffer) { + $rootScope.items = [1,2,3,4,5]; + $rootScope.$digest(); - $rootScope.$digest(); - expect(child).toBeShown(); - $animate.addClass(child, 'ng-hide'); - $rootScope.$digest(); - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(child.hasClass('ng-hide-add')).toBe(true); - expect(child.hasClass('ng-hide-add-active')).toBe(true); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } - expect(child).toBeHidden(); - })); - - - it("should exclusively animate the setClass animation event", function() { - var count = 0, fallback = jasmine.createSpy('callback'); - module(function($animateProvider) { - $animateProvider.register('.classify', function() { - return { - beforeAddClass: fallback, - addClass: fallback, - beforeRemoveClass: fallback, - removeClass: fallback, - - beforeSetClass: function(element, add, remove, done) { - count++; - expect(add).toBe('yes'); - expect(remove).toBe('no'); - done(); - }, - setClass: function(element, add, remove, done) { - count++; - expect(add).toBe('yes'); - expect(remove).toBe('no'); - done(); - } - }; - }); - }); - inject(function($animate, $rootScope) { - child.attr('class','classify no'); - $animate.setClass(child, 'yes', 'no'); - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(child.hasClass('yes')).toBe(true); - expect(child.hasClass('no')).toBe(false); - expect(count).toBe(2); - - expect(fallback).not.toHaveBeenCalled(); - }); - }); + // all the start/end repeat anchors + their adjacent comments + expect(element[0].childNodes.length).toBe(22); - it("should exclusively animate the setClass animation event with native dom elements", function() { - var count = 0, fallback = jasmine.createSpy('callback'); - module(function($animateProvider) { - $animateProvider.register('.classify', function() { - return { - beforeAddClass: fallback, - addClass: fallback, - beforeRemoveClass: fallback, - removeClass: fallback, - - beforeSetClass: function(element, add, remove, done) { - count++; - expect(add).toBe('yes'); - expect(remove).toBe('no'); - done(); - }, - setClass: function(element, add, remove, done) { - count++; - expect(add).toBe('yes'); - expect(remove).toBe('no'); - done(); - } - }; - }); - }); - inject(function($animate, $rootScope) { - child.attr('class','classify no'); - $animate.setClass(child[0], 'yes', 'no'); - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(child.hasClass('yes')).toBe(true); - expect(child.hasClass('no')).toBe(false); - expect(count).toBe(2); - - expect(fallback).not.toHaveBeenCalled(); - }); - }); + var runner = new $$AnimateRunner(); + overriddenAnimationRunner = runner; - it("should delegate down to addClass/removeClass if a setClass animation is not found", function() { - var count = 0; - module(function($animateProvider) { - $animateProvider.register('.classify', function() { - return { - beforeAddClass: function(element, className, done) { - count++; - expect(className).toBe('yes'); - done(); - }, - addClass: function(element, className, done) { - count++; - expect(className).toBe('yes'); - done(); - }, - beforeRemoveClass: function(element, className, done) { - count++; - expect(className).toBe('no'); - done(); - }, - removeClass: function(element, className, done) { - count++; - expect(className).toBe('no'); - done(); - } - }; - }); - }); - inject(function($animate, $rootScope) { - child.attr('class','classify no'); - $animate.setClass(child, 'yes', 'no'); - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(child.hasClass('yes')).toBe(true); - expect(child.hasClass('no')).toBe(false); - expect(count).toBe(4); - }); - }); + $rootScope.items.length = 0; + $rootScope.$digest(); + runner.end(); + $$rAF.flush(); - it("should assign the ng-event className to all animation events when transitions/keyframes are used", - inject(function($animate, $sniffer, $rootScope) { + // we're left with a text node and a comment node + expect(element[0].childNodes.length).toBeLessThan(3); + })); - if (!$sniffer.transitions) return; - $rootScope.$digest(); - element[0].removeChild(child[0]); + it('addClass() should issue an addClass animation with the correct DOM operation', inject(function($animate, $rootScope) { + parent.append(element); + options.foo = 'bar'; + $animate.addClass(element, 'red', options); + $rootScope.$digest(); - //enter - $animate.enter(child, element); - $rootScope.$digest(); - $animate.triggerReflow(); + expect(capturedAnimation[0]).toBe(element); + expect(capturedAnimation[1]).toBe('addClass'); + expect(capturedAnimation[2].foo).toEqual(options.foo); - expect(child.attr('class')).toContain('ng-enter'); - expect(child.attr('class')).toContain('ng-enter-active'); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - $animate.triggerCallbackPromise(); + expect(element).not.toHaveClass('red'); + applyAnimationClasses(element, capturedAnimation[2]); + expect(element).toHaveClass('red'); + })); - //move - element.append(after); - $animate.move(child, element, after); - $rootScope.$digest(); - $animate.triggerReflow(); + it('removeClass() should issue a removeClass animation with the correct DOM operation', inject(function($animate, $rootScope) { + parent.append(element); + element.addClass('blue'); - expect(child.attr('class')).toContain('ng-move'); - expect(child.attr('class')).toContain('ng-move-active'); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - $animate.triggerCallbackPromise(); + options.foo = 'bar'; + $animate.removeClass(element, 'blue', options); + $rootScope.$digest(); - //hide - $animate.addClass(child, 'ng-hide'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(child.attr('class')).toContain('ng-hide-add'); - expect(child.attr('class')).toContain('ng-hide-add-active'); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); + expect(capturedAnimation[0]).toBe(element); + expect(capturedAnimation[1]).toBe('removeClass'); + expect(capturedAnimation[2].foo).toEqual(options.foo); - //show - $animate.removeClass(child, 'ng-hide'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(child.attr('class')).toContain('ng-hide-remove'); - expect(child.attr('class')).toContain('ng-hide-remove-active'); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); + expect(element).toHaveClass('blue'); + applyAnimationClasses(element, capturedAnimation[2]); + expect(element).not.toHaveClass('blue'); + })); - //animate - $animate.animate(child, null, null, 'my-inline-animation'); - $rootScope.$digest(); - $animate.triggerReflow(); + it('setClass() should issue a setClass animation with the correct DOM operation', inject(function($animate, $rootScope) { + parent.append(element); + element.addClass('green'); - expect(child.attr('class')).toContain('my-inline-animation'); - expect(child.attr('class')).toContain('my-inline-animation-active'); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - $animate.triggerCallbackPromise(); + options.foo = 'bar'; + $animate.setClass(element, 'yellow', 'green', options); + $rootScope.$digest(); - //leave - $animate.leave(child); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(child.attr('class')).toContain('ng-leave'); - expect(child.attr('class')).toContain('ng-leave-active'); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - })); - - - it("should trigger a cancellation when the return function is called upon any animation", function() { - var captures = {}; - - module(function($animateProvider) { - $animateProvider.register('.track-me', function() { - return { - enter: track('enter'), - leave: track('leave'), - move: track('move'), - addClass: track('addClass'), - removeClass: track('removeClass'), - setClass: track('setClass') - }; - - function track(type) { - return function(element, add, remove, done) { - done = done || remove || add; - return function(cancelled) { - captures[type]=cancelled; - }; - }; - } - }); - }); - inject(function($animate, $sniffer, $rootScope) { - - var promise; - $animate.enabled(true); - $rootScope.$digest(); - element[0].removeChild(child[0]); - child.addClass('track-me'); - - //enter - promise = $animate.enter(child, element); - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(captures.enter).toBeUndefined(); - $animate.cancel(promise); - expect(captures.enter).toBeTruthy(); - $animate.triggerCallbackPromise(); - - //move - element.append(after); - promise = $animate.move(child, element, after); - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(captures.move).toBeUndefined(); - $animate.cancel(promise); - expect(captures.move).toBeTruthy(); - $animate.triggerCallbackPromise(); - - //addClass - promise = $animate.addClass(child, 'ng-hide'); - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(captures.addClass).toBeUndefined(); - $animate.cancel(promise); - expect(captures.addClass).toBeTruthy(); - $animate.triggerCallbackPromise(); - - //removeClass - promise = $animate.removeClass(child, 'ng-hide'); - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(captures.removeClass).toBeUndefined(); - $animate.cancel(promise); - expect(captures.removeClass).toBeTruthy(); - $animate.triggerCallbackPromise(); - - //setClass - child.addClass('red'); - promise = $animate.setClass(child, 'blue', 'red'); - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(captures.setClass).toBeUndefined(); - $animate.cancel(promise); - expect(captures.setClass).toBeTruthy(); - $animate.triggerCallbackPromise(); - - //leave - promise = $animate.leave(child); - $rootScope.$digest(); - - expect(captures.leave).toBeUndefined(); - $animate.cancel(promise); - expect(captures.leave).toBeTruthy(); - $animate.triggerCallbackPromise(); - }); - }); + expect(capturedAnimation[0]).toBe(element); + expect(capturedAnimation[1]).toBe('setClass'); + expect(capturedAnimation[2].foo).toEqual(options.foo); + expect(element).not.toHaveClass('yellow'); + expect(element).toHaveClass('green'); + applyAnimationClasses(element, capturedAnimation[2]); + expect(element).toHaveClass('yellow'); + expect(element).not.toHaveClass('green'); + })); - it("should not run if animations are disabled", - inject(function($animate, $rootScope, $timeout, $sniffer) { + they('$prop() should operate using a native DOM element', + ['enter', 'move', 'leave', 'addClass', 'removeClass', 'setClass', 'animate'], function(event) { - $animate.enabled(false); + inject(function($animate, $rootScope, $document) { + var element = $document[0].createElement('div'); + element.setAttribute('id', 'crazy-man'); + if (event !== 'enter' && event !== 'move') { + parent.append(element); + } - $rootScope.$digest(); + switch (event) { + case 'enter': + case 'move': + $animate[event](element, parent, parent2, options); + break; + + case 'addClass': + $animate.addClass(element, 'klass', options); + break; + + case 'removeClass': + element.className = 'klass'; + $animate.removeClass(element, 'klass', options); + break; + + case 'setClass': + element.className = 'two'; + $animate.setClass(element, 'one', 'two', options); + break; + + case 'leave': + $animate.leave(element, options); + break; + + case 'animate': + var toStyles = { color: 'red' }; + $animate.animate(element, {}, toStyles, 'klass', options); + break; + } - element.addClass('setup-memo'); + $rootScope.$digest(); + expect(capturedAnimation[0].attr('id')).toEqual(element.getAttribute('id')); + }); + }); - element.text('123'); - expect(element.text()).toBe('123'); - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); - expect(element.text()).toBe('123'); + describe('addClass / removeClass', function() { + it('should not perform an animation if there are no valid CSS classes to add', + inject(function($animate, $rootScope) { - $animate.enabled(true); + parent.append(element); - element.addClass('ng-hide'); - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); - if ($sniffer.transitions) { - $animate.triggerReflow(); - } - expect(element.text()).toBe('memento'); - })); + $animate.removeClass(element, 'something-to-remove'); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); + element.addClass('something-to-add'); - it("should only call done() once and right away if another animation takes place in between", - inject(function($animate, $rootScope, $sniffer, $timeout) { + $animate.addClass(element, 'something-to-add'); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); + })); + }); - element.append(child); - child.addClass('custom-delay'); + describe('animate()', function() { + they('should not perform an animation if $prop is provided as a `to` style', + { '{}': {}, + 'null': null, + 'false': false, + '""': "", + '[]': [] }, function(toStyle) { - expect(element).toBeShown(); - $animate.addClass(child, 'ng-hide'); + inject(function($animate, $rootScope) { + parent.append(element); + $animate.animate(element, null, toStyle); $rootScope.$digest(); - if ($sniffer.transitions) { - expect(child).toBeShown(); - } + expect(capturedAnimation).toBeFalsy(); + }); + }); - $animate.leave(child); - $rootScope.$digest(); - if ($sniffer.transitions) { - $animate.triggerReflow(); - } - expect(child).toBeHidden(); //hides instantly + it('should not perform an animation if only from styles are provided', + inject(function($animate, $rootScope) { + + var fromStyle = { color: 'pink' }; + parent.append(element); + $animate.animate(element, fromStyle); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); + })); - //lets change this to prove that done doesn't fire anymore for the previous hide() operation - child.css('display','block'); - child.removeClass('ng-hide'); + it('should perform an animation if only from styles are provided as well as any valid classes', + inject(function($animate, $rootScope) { - if ($sniffer.transitions) { - expect(element.children().length).toBe(1); //still animating - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } - $timeout.flush(2000); - $timeout.flush(2000); - expect(child).toBeShown(); + parent.append(element); - expect(element.children().length).toBe(0); - })); + var fromStyle = { color: 'red' }; + var options = { removeClass: 'goop' }; + $animate.animate(element, fromStyle, null, null, options); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); + fromStyle = { color: 'blue' }; + options = { addClass: 'goop' }; + $animate.animate(element, fromStyle, null, null, options); + $rootScope.$digest(); + expect(capturedAnimation).toBeTruthy(); + })); + }); - it("should retain existing styles of the animated element", - inject(function($animate, $rootScope, $sniffer) { + describe('parent animations', function() { + it('should immediately end a pre-digest parent class-based animation if a structural child is active', + inject(function($rootScope, $animate) { - element.append(child); - child.attr('style', 'width: 20px'); + parent.append(element); + var child = jqLite('
'); + $animate.addClass(parent, 'abc'); - $animate.addClass(child, 'ng-hide'); - $rootScope.$digest(); + $animate.enter(child, element); + $rootScope.$digest(); - $animate.leave(child); - $rootScope.$digest(); + expect(parent).toHaveClass('abc'); + })); - if ($sniffer.transitions) { - $animate.triggerReflow(); + it('should immediately end a parent class-based animation if a structural child is active', + inject(function($rootScope, $rootElement, $animate) { - //this is to verify that the existing style is appended with a semicolon automatically - expect(child.attr('style')).toMatch(/width: 20px;.*?/i); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); + parent.append(element); + var child = jqLite('
'); + + var isCancelled = false; + overriddenAnimationRunner = extend(defaultFakeAnimationRunner, { + end: function() { + isCancelled = true; } + }); - expect(child.attr('style')).toMatch(/width: 20px/i); - })); + $animate.addClass(parent, 'abc'); + $rootScope.$digest(); + // restore the default + overriddenAnimationRunner = defaultFakeAnimationRunner; - it("should call the cancel callback when another animation is called on the same element", - inject(function($animate, $rootScope, $sniffer, $timeout) { + $animate.enter(child, element); + $rootScope.$digest(); - element.append(child); + expect(isCancelled).toBe(true); + })); + }); - child.addClass('custom-delay ng-hide'); - $animate.removeClass(child, 'ng-hide'); - $rootScope.$digest(); - if ($sniffer.transitions) { - $animate.triggerReflow(); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } - $timeout.flush(2000); + it("should NOT clobber all data on an element when animation is finished", + inject(function($animate, $rootScope) { - $animate.addClass(child, 'ng-hide'); + element.data('foo', 'bar'); - expect(child.hasClass('animation-cancelled')).toBe(true); - })); + $animate.removeClass(element, 'ng-hide'); + $rootScope.$digest(); + $animate.addClass(element, 'ng-hide'); + $rootScope.$digest(); - it("should remove the .ng-animate class after the next animation is run which interrupted the last animation", function() { - var addClassDone, removeClassDone, - addClassDoneSpy = jasmine.createSpy(), - removeClassDoneSpy = jasmine.createSpy(); + expect(element.data('foo')).toEqual('bar'); + })); - module(function($animateProvider) { - $animateProvider.register('.hide', function() { - return { - addClass: function(element, className, done) { - addClassDone = done; - return addClassDoneSpy; - }, - removeClass: function(element, className, done) { - removeClassDone = done; - return removeClassDoneSpy; - } - }; - }); - }); + describe('child animations', function() { + it('should skip animations if the element is not attached to the $rootElement', + inject(function($compile, $rootScope, $animate) { - inject(function($animate, $rootScope) { - $animate.addClass(element, 'hide'); - $rootScope.$digest(); + $animate.enabled(true); - expect(element).toHaveClass('ng-animate'); + var elm1 = $compile('
')($rootScope); - $animate.triggerReflow(); + expect(capturedAnimation).toBeFalsy(); + $animate.addClass(elm1, 'klass2'); + expect(capturedAnimation).toBeFalsy(); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); + })); - $animate.removeClass(element, 'hide'); - $rootScope.$digest(); - expect(addClassDoneSpy).toHaveBeenCalled(); + it('should skip animations if the element is attached to the $rootElement, but not apart of the body', + inject(function($compile, $rootScope, $animate, $rootElement) { - $animate.triggerReflow(); + $animate.enabled(true); - expect(element).toHaveClass('ng-animate'); + var elm1 = $compile('
')($rootScope); - removeClassDone(); - $animate.triggerCallbackPromise(); + var newParent = $compile('
')($rootScope); + newParent.append($rootElement); + $rootElement.append(elm1); - expect(element).not.toHaveClass('ng-animate'); - }); - }); + expect(capturedAnimation).toBeFalsy(); + $animate.addClass(elm1, 'klass2'); + expect(capturedAnimation).toBeFalsy(); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); + })); - it("should skip a class-based animation if the same element already has an ongoing structural animation", - inject(function($animate, $rootScope, $sniffer) { + it('should skip the animation if the element is removed from the DOM before the post digest kicks in', + inject(function($animate, $rootScope) { - var completed = false; - $animate.enter(child, element, null).then(function() { - completed = true; - }); - $rootScope.$digest(); + $animate.enter(element, parent); + expect(capturedAnimation).toBeFalsy(); - expect(completed).toBe(false); + element.remove(); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); + })); - $animate.addClass(child, 'green'); - $rootScope.$digest(); - expect(element.hasClass('green')); + it('should be blocked when there is an ongoing structural parent animation occurring', + inject(function($rootScope, $rootElement, $animate) { - expect(completed).toBe(false); - if ($sniffer.transitions) { - $animate.triggerReflow(); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } - $animate.triggerCallbackPromise(); - - expect(completed).toBe(true); - })); - - it("should skip class-based animations if animations are directly disabled on the same element", function() { - var capture; - module(function($animateProvider) { - $animateProvider.register('.capture', function() { - return { - addClass: function(element, className, done) { - capture = true; - done(); - } - }; - }); - }); - inject(function($animate, $rootScope) { - $animate.enabled(true); - $animate.enabled(false, element); - - $animate.addClass(element, 'capture'); - $rootScope.$digest(); - expect(element.hasClass('capture')).toBe(true); - expect(capture).not.toBe(true); - }); - }); + parent.append(element); - it("should not apply a cancellation when addClass is done multiple times", - inject(function($animate, $rootScope, $sniffer, $timeout) { + expect(capturedAnimation).toBeFalsy(); + $animate.move(parent, parent2); + $rootScope.$digest(); - element.append(child); + // yes the animation is going on + expect(capturedAnimation[0]).toBe(parent); + capturedAnimation = null; - $animate.addClass(child, 'custom-delay'); - $rootScope.$digest(); + $animate.addClass(element, 'blue'); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); + })); - $animate.addClass(child, 'custom-long-delay'); - $rootScope.$digest(); + it("should disable all child animations for atleast one RAF when a structural animation is issued", + inject(function($animate, $rootScope, $compile, $document, $rootElement, $$rAF, $$AnimateRunner) { - $animate.triggerReflow(); + element = $compile( + '
' + + '
' + + ' {{ item }}' + + '
' + + '
' + )($rootScope); - expect(child.hasClass('animation-cancelled')).toBe(false); - expect(child.hasClass('animation-ended')).toBe(false); + jqLite($document[0].body).append($rootElement); + $rootElement.append(element); - $timeout.flush(); - expect(child.hasClass('animation-ended')).toBe(true); - })); + var runner = new $$AnimateRunner(); + overriddenAnimationRunner = runner; + $rootScope.items = [1]; + $rootScope.$digest(); - it("should NOT clobber all data on an element when animation is finished", - inject(function($animate, $rootScope) { + expect(capturedAnimation[0]).toHaveClass('if-animation'); + expect(capturedAnimationHistory.length).toBe(1); + expect(element[0].querySelectorAll('.repeat-animation').length).toBe(1); - child.css('display','none'); - element.data('foo', 'bar'); + $rootScope.items = [1, 2]; + $rootScope.$digest(); - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); + expect(capturedAnimation[0]).toHaveClass('if-animation'); + expect(capturedAnimationHistory.length).toBe(1); + expect(element[0].querySelectorAll('.repeat-animation').length).toBe(2); - $animate.addClass(element, 'ng-hide'); - $rootScope.$digest(); + runner.end(); + $$rAF.flush(); - expect(element.data('foo')).toEqual('bar'); - })); + $rootScope.items = [1, 2, 3]; + $rootScope.$digest(); + expect(capturedAnimation[0]).toHaveClass('repeat-animation'); + expect(capturedAnimationHistory.length).toBe(2); + expect(element[0].querySelectorAll('.repeat-animation').length).toBe(3); + })); - it("should allow multiple JS animations which run in parallel", - inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { + it('should not be blocked when there is an ongoing class-based parent animation occurring', + inject(function($rootScope, $rootElement, $animate) { - $animate.addClass(element, 'custom-delay custom-long-delay'); - $rootScope.$digest(); - $animate.triggerReflow(); - $timeout.flush(2000); - $timeout.flush(20000); - expect(element.hasClass('custom-delay')).toBe(true); - expect(element.hasClass('custom-long-delay')).toBe(true); - }) - ); + parent.append(element); + expect(capturedAnimation).toBeFalsy(); + $animate.addClass(parent, 'rogers'); + $rootScope.$digest(); - it("should allow both multiple JS and CSS animations which run in parallel", - inject(function($animate, $rootScope, $compile, $sniffer, $timeout, _$rootElement_) { - $rootElement = _$rootElement_; + // yes the animation is going on + expect(capturedAnimation[0]).toBe(parent); + capturedAnimation = null; - ss.addRule('.ng-hide-add', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); - ss.addRule('.ng-hide-remove', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); + $animate.addClass(element, 'blue'); + $rootScope.$digest(); + expect(capturedAnimation[0]).toBe(element); + })); - element = $compile(html('
1
'))($rootScope); - element.addClass('custom-delay custom-long-delay'); - $rootScope.$digest(); + it('should skip all pre-digest queued child animations when a parent structural animation is triggered', + inject(function($rootScope, $rootElement, $animate) { - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); + parent.append(element); - if ($sniffer.transitions) { - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } - $timeout.flush(2000); - $timeout.flush(20000); - - expect(element.hasClass('custom-delay')).toBe(true); - expect(element.hasClass('custom-delay-add')).toBe(false); - expect(element.hasClass('custom-delay-add-active')).toBe(false); - - expect(element.hasClass('custom-long-delay')).toBe(true); - expect(element.hasClass('custom-long-delay-add')).toBe(false); - expect(element.hasClass('custom-long-delay-add-active')).toBe(false); - })); - - it('should apply directive styles and provide the style collection to the animation function', function() { - var animationDone; - var animationStyles; - var proxyAnimation = function() { - var limit = arguments.length - 1; - animationStyles = arguments[limit]; - animationDone = arguments[limit - 1]; - }; - module(function($animateProvider) { - $animateProvider.register('.capture', function() { - return { - enter: proxyAnimation, - leave: proxyAnimation, - move: proxyAnimation, - addClass: proxyAnimation, - removeClass: proxyAnimation, - setClass: proxyAnimation - }; - }); - }); - inject(function($animate, $rootScope, $compile, $sniffer, $timeout, _$rootElement_) { - $rootElement = _$rootElement_; - - $animate.enabled(true); - - element = $compile(html('
'))($rootScope); - var otherParent = $compile('
')($rootScope); - var child = $compile('
')($rootScope); - - $rootElement.append(otherParent); - $rootScope.$digest(); - - var styles = { - from: { backgroundColor: 'blue' }, - to: { backgroundColor: 'red' } - }; - - //enter - $animate.enter(child, element, null, styles); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(animationStyles).toEqual(styles); - animationDone(); - animationDone = animationStyles = null; - $animate.triggerCallbacks(); - - //move - $animate.move(child, null, otherParent, styles); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(animationStyles).toEqual(styles); - animationDone(); - animationDone = animationStyles = null; - $animate.triggerCallbacks(); - - //addClass - $animate.addClass(child, 'on', styles); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(animationStyles).toEqual(styles); - animationDone(); - animationDone = animationStyles = null; - $animate.triggerCallbacks(); - - //setClass - $animate.setClass(child, 'off', 'on', styles); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(animationStyles).toEqual(styles); - animationDone(); - animationDone = animationStyles = null; - $animate.triggerCallbacks(); - - //removeClass - $animate.removeClass(child, 'off', styles); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(animationStyles).toEqual(styles); - animationDone(); - animationDone = animationStyles = null; - $animate.triggerCallbacks(); - - //leave - $animate.leave(child, styles); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(animationStyles).toEqual(styles); - animationDone(); - animationDone = animationStyles = null; - $animate.triggerCallbacks(); - - dealoc(otherParent); - }); - }); - }); + $animate.addClass(element, 'rumlow'); + $animate.move(parent, null, parent2); - it("should apply animated styles even if there are no detected animations", - inject(function($compile, $animate, $rootScope, $sniffer, $rootElement, $document) { + expect(capturedAnimation).toBeFalsy(); + expect(capturedAnimationHistory.length).toBe(0); + $rootScope.$digest(); - $animate.enabled(true); - jqLite($document[0].body).append($rootElement); + expect(capturedAnimation[0]).toBe(parent); + expect(capturedAnimationHistory.length).toBe(1); + })); - element = $compile('
')($rootScope); + it('should end all ongoing post-digest child animations when a parent structural animation is triggered', + inject(function($rootScope, $rootElement, $animate) { - $animate.enter(element, $rootElement, null, { - to: {borderColor: 'red'} + parent.append(element); + + $animate.addClass(element, 'rumlow'); + var isCancelled = false; + overriddenAnimationRunner = extend(defaultFakeAnimationRunner, { + end: function() { + isCancelled = true; + } }); $rootScope.$digest(); - expect(element).toHaveClass('ng-animate'); + expect(capturedAnimation[0]).toBe(element); + expect(isCancelled).toBe(false); - $animate.triggerReflow(); - $animate.triggerCallbacks(); + // restore the default + overriddenAnimationRunner = defaultFakeAnimationRunner; + $animate.move(parent, null, parent2); + $rootScope.$digest(); + expect(capturedAnimation[0]).toBe(parent); - expect(element).not.toHaveClass('ng-animate'); - expect(element.attr('style')).toMatch(/border-color: red/); + expect(isCancelled).toBe(true); })); - describe("with CSS3", function() { + it('should not end any child animations if a parent class-based animation is issued', + inject(function($rootScope, $rootElement, $animate) { - beforeEach(function() { - module(function() { - return function(_$rootElement_) { - $rootElement = _$rootElement_; - }; - }); - }); + parent.append(element); - /* The CSS animation handler must always be rendered before the other JS animation - handlers. This is important since the CSS animation handler may place temporary - styling on the HTML element before the reflow commences which in turn may override - other transition or keyframe styles that any former JS animations may have placed - on the element: https://github.com/angular/angular.js/issues/6675 */ - it("should always perform the CSS animation before the JS animation", function() { - var log = []; - module(function($animateProvider) { - //CSS animation handler - $animateProvider.register('', function() { - return { - leave: function() { log.push('css'); } - }; - }); - //custom JS animation handler - $animateProvider.register('.js-animation', function() { - return { - leave: function() { log.push('js'); } - }; - }); - }); - inject(function($animate, $rootScope, $compile, $sniffer) { - if (!$sniffer.transitions) return; - - element = $compile(html('
'))($rootScope); - $animate.leave(element); - $rootScope.$digest(); - expect(log).toEqual(['css','js']); - }); + var element2 = jqLite('
element2
'); + $animate.enter(element2, parent); + + var isCancelled = false; + overriddenAnimationRunner = extend(defaultFakeAnimationRunner, { + end: function() { + isCancelled = true; + } }); + $rootScope.$digest(); + expect(capturedAnimation[0]).toBe(element2); + expect(isCancelled).toBe(false); - describe("Animations", function() { + // restore the default + overriddenAnimationRunner = defaultFakeAnimationRunner; + $animate.addClass(parent, 'peter'); + $rootScope.$digest(); + expect(capturedAnimation[0]).toBe(parent); - it("should properly detect and make use of CSS Animations", - inject(function($animate, $rootScope, $compile, $sniffer) { + expect(isCancelled).toBe(false); + })); - ss.addRule('.ng-hide-add', - '-webkit-animation: some_animation 4s linear 0s 1 alternate;' + - 'animation: some_animation 4s linear 0s 1 alternate;'); - ss.addRule('.ng-hide-remove', - '-webkit-animation: some_animation 4s linear 0s 1 alternate;' + - 'animation: some_animation 4s linear 0s 1 alternate;'); + it('should allow follow-up class-based animations to run in parallel on the same element', + inject(function($rootScope, $animate, $$rAF) { - element = $compile(html('
1
'))($rootScope); + parent.append(element); - element.addClass('ng-hide'); - expect(element).toBeHidden(); + var runner1done = false; + var runner1 = $animate.addClass(element, 'red'); + runner1.done(function() { + runner1done = true; + }); - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); - if ($sniffer.animations) { - $animate.triggerReflow(); - browserTrigger(element,'animationend', { timeStamp: Date.now() + 4000, elapsedTime: 4 }); - } - expect(element).toBeShown(); - })); + $rootScope.$digest(); + $$rAF.flush(); + expect(capturedAnimation).toBeTruthy(); + expect(runner1done).toBeFalsy(); + capturedAnimation = null; - it("should properly detect and make use of CSS Animations with multiple iterations", - inject(function($animate, $rootScope, $compile, $sniffer) { + // make sure it's a different runner + overriddenAnimationRunner = extend(defaultFakeAnimationRunner, { + end: function() { + // this code will still end the animation, just not at any deeper level + } + }); - var style = '-webkit-animation-duration: 2s;' + - '-webkit-animation-iteration-count: 3;' + - 'animation-duration: 2s;' + - 'animation-iteration-count: 3;'; + var runner2done = false; + var runner2 = $animate.addClass(element, 'blue'); + runner2.done(function() { + runner2done = true; + }); - ss.addRule('.ng-hide-add', style); - ss.addRule('.ng-hide-remove', style); + $rootScope.$digest(); + $$rAF.flush(); + expect(capturedAnimation).toBeTruthy(); + expect(runner2done).toBeFalsy(); - element = $compile(html('
1
'))($rootScope); + expect(runner1done).toBeFalsy(); - element.addClass('ng-hide'); - expect(element).toBeHidden(); + runner2.end(); - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); - if ($sniffer.animations) { - $animate.triggerReflow(); - browserTrigger(element,'animationend', { timeStamp: Date.now() + 6000, elapsedTime: 6 }); - } - expect(element).toBeShown(); - })); + expect(runner2done).toBeTruthy(); + expect(runner1done).toBeFalsy(); + })); + it('should remove the animation block on child animations once the parent animation is complete', + inject(function($rootScope, $rootElement, $animate, $$AnimateRunner, $$rAF) { - it("should not consider the animation delay is provided", - inject(function($animate, $rootScope, $compile, $sniffer) { + var runner = new $$AnimateRunner(); + overriddenAnimationRunner = runner; + parent.append(element); - var style = '-webkit-animation-duration: 2s;' + - '-webkit-animation-delay: 10s;' + - '-webkit-animation-iteration-count: 5;' + - 'animation-duration: 2s;' + - 'animation-delay: 10s;' + - 'animation-iteration-count: 5;'; + $animate.enter(parent, null, parent2); + $rootScope.$digest(); + expect(capturedAnimationHistory.length).toBe(1); - ss.addRule('.ng-hide-add', style); - ss.addRule('.ng-hide-remove', style); + $animate.addClass(element, 'tony'); + $rootScope.$digest(); + expect(capturedAnimationHistory.length).toBe(1); - element = $compile(html('
1
'))($rootScope); + runner.end(); + $$rAF.flush(); - element.addClass('ng-hide'); - expect(element).toBeHidden(); + $animate.addClass(element, 'stark'); + $rootScope.$digest(); + expect(capturedAnimationHistory.length).toBe(2); + })); + }); - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); - if ($sniffer.transitions) { - $animate.triggerReflow(); - browserTrigger(element,'animationend', { timeStamp: Date.now() + 20000, elapsedTime: 10 }); - } - expect(element).toBeShown(); - })); + describe('cancellations', function() { + it('should cancel the previous animation if a follow-up structural animation takes over', + inject(function($animate, $rootScope) { + var enterComplete = false; + overriddenAnimationRunner = extend(defaultFakeAnimationRunner, { + end: function() { + enterComplete = true; + } + }); - it("should skip animations if disabled and run when enabled", - inject(function($animate, $rootScope, $compile) { - $animate.enabled(false); - var style = '-webkit-animation: some_animation 2s linear 0s 1 alternate;' + - 'animation: some_animation 2s linear 0s 1 alternate;'; + parent.append(element); + $animate.move(element, parent2); - ss.addRule('.ng-hide-add', style); - ss.addRule('.ng-hide-remove', style); + $rootScope.$digest(); + expect(enterComplete).toBe(false); - element = $compile(html('
1
'))($rootScope); - element.addClass('ng-hide'); - expect(element).toBeHidden(); - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); - expect(element).toBeShown(); - })); + $animate.leave(element); + $rootScope.$digest(); + expect(enterComplete).toBe(true); + })); + it('should skip the class-based animation entirely if there is an active structural animation', + inject(function($animate, $rootScope) { - it("should finish the previous animation when a new animation is started", - inject(function($animate, $rootScope, $compile, $sniffer) { - var style = '-webkit-animation: some_animation 2s linear 0s 1 alternate;' + - 'animation: some_animation 2s linear 0s 1 alternate;'; + $animate.enter(element, parent); + $rootScope.$digest(); + expect(capturedAnimation).toBeTruthy(); - ss.addRule('.ng-hide-add', style); - ss.addRule('.ng-hide-remove', style); + capturedAnimation = null; + $animate.addClass(element, 'red'); + $rootScope.$digest(); + expect(element).toHaveClass('red'); + })); - element = $compile(html('
1
'))($rootScope); - element.addClass('custom'); + it('should issue a new runner instance if a previous structural animation was cancelled', + inject(function($animate, $rootScope) { - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); + parent.append(element); - if ($sniffer.animations) { - $animate.triggerReflow(); - expect(element.hasClass('ng-hide-remove')).toBe(true); - expect(element.hasClass('ng-hide-remove-active')).toBe(true); - } + var runner1 = $animate.move(element, parent2); + $rootScope.$digest(); - element.removeClass('ng-hide'); - $animate.addClass(element, 'ng-hide'); - $rootScope.$digest(); - - expect(element.hasClass('ng-hide-remove')).toBe(false); //added right away - - if ($sniffer.animations) { //cleanup some pending animations - $animate.triggerReflow(); - expect(element.hasClass('ng-hide-add')).toBe(true); - expect(element.hasClass('ng-hide-add-active')).toBe(true); - browserTrigger(element,'animationend', { timeStamp: Date.now() + 2000, elapsedTime: 2 }); - } - - expect(element.hasClass('ng-hide-remove-active')).toBe(false); - }) - ); - - it("should piggy-back-transition the styles with the max keyframe duration if provided by the directive", - inject(function($compile, $animate, $rootScope, $sniffer) { - - $animate.enabled(true); - ss.addRule('.on', '-webkit-animation: 1s keyframeanimation; animation: 1s keyframeanimation;'); - - element = $compile(html('
1
'))($rootScope); - - $animate.addClass(element, 'on', { - to: {borderColor: 'blue'} - }); - - $rootScope.$digest(); - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(element.attr('style')).toContain('border-color: blue'); - expect(element.attr('style')).toMatch(/transition:.*1s/); - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } - - expect(element.attr('style')).toContain('border-color: blue'); - })); - - it("should not apply a piggy-back-transition if the styles object contains no styles", - inject(function($compile, $animate, $rootScope, $sniffer) { - - if (!$sniffer.animations) return; - - $animate.enabled(true); - ss.addRule('.on', '-webkit-animation: 1s super-animation; animation: 1s super-animation;'); - - element = $compile(html('
1
'))($rootScope); - - $animate.addClass(element, 'on', { - to: {} - }); - - $rootScope.$digest(); - $animate.triggerReflow(); - expect(element.attr('style')).not.toMatch(/transition/); - })); - - it("should pause the playstate when performing a stagger animation", - inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { - - if (!$sniffer.animations) return; - - $animate.enabled(true); - - ss.addRule('.real-animation.ng-enter, .real-animation.ng-leave', - '-webkit-animation:1s my_animation;' + - 'animation:1s my_animation;'); - - ss.addRule('.real-animation.ng-enter-stagger, .real-animation.ng-leave-stagger', - '-webkit-animation-delay:0.1s;' + - '-webkit-animation-duration:0s;' + - 'animation-delay:0.1s;' + - 'animation-duration:0s;'); - - ss.addRule('.fake-animation.ng-enter-stagger, .fake-animation.ng-leave-stagger', - '-webkit-animation-delay:0.1s;' + - '-webkit-animation-duration:1s;' + - 'animation-delay:0.1s;' + - 'animation-duration:1s;'); - - var container = $compile(html('
'))($rootScope); - - var newScope, element, elements = []; - for (var i = 0; i < 5; i++) { - newScope = $rootScope.$new(); - element = $compile('
')(newScope); - $animate.enter(element, container); - elements.push(element); - } - - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(elements[0].attr('style')).toBeFalsy(); - for (i = 1; i < 5; i++) { - expect(elements[i].attr('style')).toMatch(/animation-play-state:\s*paused/); - } - - //final closing timeout - $timeout.flush(); - - for (i = 0; i < 5; i++) { - dealoc(elements[i]); - newScope = $rootScope.$new(); - element = $compile('
')(newScope); - $animate.enter(element, container); - elements[i] = element; - } - - $rootScope.$digest(); - - //this means no animations were triggered - $timeout.verifyNoPendingTasks(); - - expect(elements[0].attr('style')).toBeFalsy(); - for (i = 1; i < 5; i++) { - expect(elements[i].attr('style')).not.toMatch(/animation-play-state:\s*paused/); - } - })); - - - it("should block and unblock keyframe animations when a stagger animation kicks in while skipping the first element", - inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { - - if (!$sniffer.animations) return; - - $animate.enabled(true); - - ss.addRule('.blocked-animation.ng-enter', - '-webkit-animation:my_animation 1s;' + - 'animation:my_animation 1s;'); - - ss.addRule('.blocked-animation.ng-enter-stagger', - '-webkit-animation-delay:0.2s;' + - 'animation-delay:0.2s;'); - - var container = $compile(html('
'))($rootScope); - - var elements = []; - for (var i = 0; i < 4; i++) { - var newScope = $rootScope.$new(); - var element = $compile('
')(newScope); - $animate.enter(element, container); - elements.push(element); - } - - $rootScope.$digest(); - - expect(elements[0].attr('style')).toBeUndefined(); - for (i = 1; i < 4; i++) { - expect(elements[i].attr('style')).toMatch(/animation-play-state:\s*paused/); - } - - $animate.triggerReflow(); - - expect(elements[0].attr('style')).toBeUndefined(); - for (i = 1; i < 4; i++) { - expect(elements[i].attr('style')).toMatch(/animation-play-state:\s*paused/); - } - - $timeout.flush(800); - - for (i = 1; i < 4; i++) { - expect(elements[i].attr('style')).not.toMatch(/animation-play-state/); - } - })); - - it("should stagger items when multiple animation durations/delays are defined", - inject(function($animate, $rootScope, $compile, $sniffer, $timeout, $document, $rootElement, $window) { - - if (!$sniffer.transitions) return; - - $animate.enabled(true); - - ss.addRule('.stagger-animation.ng-enter, .stagger-animation.ng-leave', - '-webkit-animation:my_animation 1s 1s, your_animation 1s 2s;' + - 'animation:my_animation 1s 1s, your_animation 1s 2s;'); - - ss.addRule('.stagger-animation.ng-enter-stagger, .stagger-animation.ng-leave-stagger', - '-webkit-animation-delay:0.1s;' + - 'animation-delay:0.1s;'); - - var container = $compile(html('
'))($rootScope); - - var elements = []; - for (var i = 0; i < 4; i++) { - var newScope = $rootScope.$new(); - var element = $compile('
')(newScope); - $animate.enter(element, container); - elements.push(element); - } - - $rootScope.$digest(); - $animate.triggerReflow(); - - for (i = 1; i < 4; i++) { - expect(elements[i]).not.toHaveClass('ng-enter-active'); - expect(elements[i]).toHaveClass('ng-enter-pending'); - expect(getMaxValue('animationDelay', elements[i], $window)).toBe(2); - } - - $timeout.flush(300); - - for (i = 1; i < 4; i++) { - expect(elements[i]).toHaveClass('ng-enter-active'); - expect(elements[i]).not.toHaveClass('ng-enter-pending'); - expect(getMaxValue('animationDelay', elements[i], $window)).toBe(2); - } - })); - - it("should stagger items and apply the transition + directive styles the right time when piggy-back styles are used", - inject(function($animate, $rootScope, $compile, $sniffer, $timeout, $document, $rootElement, $window) { - - if (!$sniffer.transitions) return; - - $animate.enabled(true); - - ss.addRule('.stagger-animation.ng-enter, .stagger-animation.ng-leave', - '-webkit-animation:my_animation 1s 1s, your_animation 1s 2s;' + - 'animation:my_animation 1s 1s, your_animation 1s 2s;'); - - ss.addRule('.stagger-animation.ng-enter-stagger, .stagger-animation.ng-leave-stagger', - '-webkit-animation-delay:0.1s;' + - 'animation-delay:0.1s;'); - - var styles = { - from: { left: '50px' }, - to: { left: '100px' } - }; - var container = $compile(html('
'))($rootScope); - - var elements = []; - for (var i = 0; i < 4; i++) { - var newScope = $rootScope.$new(); - var element = $compile('
')(newScope); - $animate.enter(element, container, null, styles); - elements.push(element); - } - - $rootScope.$digest(); - - for (i = 0; i < 4; i++) { - expect(elements[i]).toHaveClass('ng-enter'); - assertTransitionDuration(elements[i], '2', true); - assertLeftStyle(elements[i], '50'); - } - - $animate.triggerReflow(); - - expect(elements[0]).toHaveClass('ng-enter-active'); - assertLeftStyle(elements[0], '100'); - assertTransitionDuration(elements[0], '1'); - - for (i = 1; i < 4; i++) { - expect(elements[i]).not.toHaveClass('ng-enter-active'); - assertTransitionDuration(elements[i], '1', true); - assertLeftStyle(elements[i], '100', true); - } - - $timeout.flush(300); - - for (i = 1; i < 4; i++) { - expect(elements[i]).toHaveClass('ng-enter-active'); - assertTransitionDuration(elements[i], '1'); - assertLeftStyle(elements[i], '100'); - } - - $timeout.flush(); - - for (i = 0; i < 4; i++) { - expect(elements[i]).not.toHaveClass('ng-enter'); - expect(elements[i]).not.toHaveClass('ng-enter-active'); - assertTransitionDuration(elements[i], '1', true); - assertLeftStyle(elements[i], '100'); - } - - function assertLeftStyle(element, val, not) { - var regex = new RegExp('left: ' + val + 'px'); - var style = element.attr('style'); - not ? expect(style).not.toMatch(regex) - : expect(style).toMatch(regex); - } - - function assertTransitionDuration(element, val, not) { - var regex = new RegExp('transition:.*' + val + 's'); - var style = element.attr('style'); - not ? expect(style).not.toMatch(regex) - : expect(style).toMatch(regex); - } - })); - }); - - - describe("Transitions", function() { - - it("should skip transitions if disabled and run when enabled", - inject(function($animate, $rootScope, $compile, $sniffer) { - - var style = '-webkit-transition: 1s linear all;' + - 'transition: 1s linear all;'; - - ss.addRule('.ng-hide-add', style); - ss.addRule('.ng-hide-remove', style); - - $animate.enabled(false); - element = $compile(html('
1
'))($rootScope); - - element.addClass('ng-hide'); - expect(element).toBeHidden(); - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); - expect(element).toBeShown(); - - $animate.enabled(true); - - element.addClass('ng-hide'); - expect(element).toBeHidden(); - - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); - if ($sniffer.transitions) { - $animate.triggerReflow(); - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } - expect(element).toBeShown(); - })); - - - it("should skip animations if disabled and run when enabled picking the longest specified duration", - inject(function($animate, $rootScope, $compile, $sniffer) { - - var style = '-webkit-transition-duration: 1s, 2000ms, 1s;' + - '-webkit-transition-property: height, left, opacity;' + - 'transition-duration: 1s, 2000ms, 1s;' + - 'transition-property: height, left, opacity;'; - - ss.addRule('.ng-hide-add', style); - ss.addRule('.ng-hide-remove', style); - - element = $compile(html('
foo
'))($rootScope); - element.addClass('ng-hide'); - - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); - - if ($sniffer.transitions) { - $animate.triggerReflow(); - var now = Date.now(); - browserTrigger(element,'transitionend', { timeStamp: now + 1000, elapsedTime: 1 }); - browserTrigger(element,'transitionend', { timeStamp: now + 1000, elapsedTime: 1 }); - browserTrigger(element,'transitionend', { timeStamp: now + 2000, elapsedTime: 2 }); - expect(element.hasClass('ng-animate')).toBe(false); - } - expect(element).toBeShown(); - })); - - - it("should skip animations if disabled and run when enabled picking the longest specified duration/delay combination", - inject(function($animate, $rootScope, $compile, $sniffer) { - $animate.enabled(false); - var style = '-webkit-transition-duration: 1s, 0s, 1s; ' + - '-webkit-transition-delay: 2s, 1000ms, 2s; ' + - '-webkit-transition-property: height, left, opacity;' + - 'transition-duration: 1s, 0s, 1s; ' + - 'transition-delay: 2s, 1000ms, 2s; ' + - 'transition-property: height, left, opacity;'; - - ss.addRule('.ng-hide-add', style); - ss.addRule('.ng-hide-remove', style); - - element = $compile(html('
foo
'))($rootScope); - - element.addClass('ng-hide'); - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); - - expect(element).toBeShown(); - $animate.enabled(true); - - element.addClass('ng-hide'); - expect(element).toBeHidden(); - - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); - if ($sniffer.transitions) { - $animate.triggerReflow(); - var now = Date.now(); - browserTrigger(element,'transitionend', { timeStamp: now + 1000, elapsedTime: 1 }); - browserTrigger(element,'transitionend', { timeStamp: now + 3000, elapsedTime: 3 }); - browserTrigger(element,'transitionend', { timeStamp: now + 3000, elapsedTime: 3 }); - } - expect(element).toBeShown(); - }) - ); - - - it("should NOT overwrite styles with outdated values when animation completes", - inject(function($animate, $rootScope, $compile, $sniffer) { - - if (!$sniffer.transitions) return; - - var style = '-webkit-transition-duration: 1s, 2000ms, 1s;' + - '-webkit-transition-property: height, left, opacity;' + - 'transition-duration: 1s, 2000ms, 1s;' + - 'transition-property: height, left, opacity;'; - - ss.addRule('.ng-hide-add', style); - ss.addRule('.ng-hide-remove', style); - - element = $compile(html('
foo
'))($rootScope); - element.addClass('ng-hide'); - - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); - - $animate.triggerReflow(); - - var now = Date.now(); - browserTrigger(element,'transitionend', { timeStamp: now + 1000, elapsedTime: 1 }); - browserTrigger(element,'transitionend', { timeStamp: now + 1000, elapsedTime: 1 }); - - element.css('width', '200px'); - browserTrigger(element,'transitionend', { timeStamp: now + 2000, elapsedTime: 2 }); - expect(element.css('width')).toBe("200px"); - })); - - it("should NOT overwrite styles when a transition with a specific property is used", - inject(function($animate, $rootScope, $compile, $sniffer) { - - if (!$sniffer.transitions) return; - - var style = '-webkit-transition: border linear .2s;' + - 'transition: border linear .2s;'; - - ss.addRule('.on', style); - element = $compile(html('
'))($rootScope); - $animate.addClass(element, 'on'); - $rootScope.$digest(); - - $animate.triggerReflow(); - - var now = Date.now(); - browserTrigger(element,'transitionend', { timeStamp: now + 200, elapsedTime: 0.2 }); - expect(element.css('height')).toBe("200px"); - })); - - - it("should animate for the highest duration", - inject(function($animate, $rootScope, $compile, $sniffer) { - var style = '-webkit-transition:1s linear all 2s;' + - 'transition:1s linear all 2s;' + - '-webkit-animation:my_ani 10s 1s;' + - 'animation:my_ani 10s 1s;'; - - ss.addRule('.ng-hide-add', style); - ss.addRule('.ng-hide-remove', style); - - element = $compile(html('
foo
'))($rootScope); - - element.addClass('ng-hide'); - expect(element).toBeHidden(); - - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); - if ($sniffer.transitions) { - $animate.triggerReflow(); - } - expect(element).toBeShown(); - if ($sniffer.transitions) { - expect(element.hasClass('ng-hide-remove-active')).toBe(true); - browserTrigger(element,'animationend', { timeStamp: Date.now() + 11000, elapsedTime: 11 }); - expect(element.hasClass('ng-hide-remove-active')).toBe(false); - } - }) - ); - - - it("should finish the previous transition when a new animation is started", - inject(function($animate, $rootScope, $compile, $sniffer) { - var style = '-webkit-transition: 1s linear all;' + - 'transition: 1s linear all;'; - - ss.addRule('.ng-hide-add', style); - ss.addRule('.ng-hide-remove', style); - - element = $compile(html('
1
'))($rootScope); - - element.addClass('ng-hide'); - $animate.removeClass(element, 'ng-hide'); - $rootScope.$digest(); - - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(element.hasClass('ng-hide-remove')).toBe(true); - expect(element.hasClass('ng-hide-remove-active')).toBe(true); - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } - expect(element.hasClass('ng-hide-remove')).toBe(false); - expect(element.hasClass('ng-hide-remove-active')).toBe(false); - expect(element).toBeShown(); - - $animate.addClass(element, 'ng-hide'); - $rootScope.$digest(); - - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(element.hasClass('ng-hide-add')).toBe(true); - expect(element.hasClass('ng-hide-add-active')).toBe(true); - } - }) - ); - - it("should place a hard block when a structural CSS transition is run", - inject(function($animate, $rootScope, $compile, $sniffer) { - - if (!$sniffer.transitions) return; - - ss.addRule('.leave-animation.ng-leave', - '-webkit-transition:5s linear all;' + - 'transition:5s linear all;' + - 'opacity:1;'); - - ss.addRule('.leave-animation.ng-leave.ng-leave-active', 'opacity:1'); - - element = $compile(html('
1
'))($rootScope); - - $animate.leave(element); - $rootScope.$digest(); - - expect(element.attr('style')).toMatch(/transition.*?:\s*none/); - - $animate.triggerReflow(); - - expect(element.attr('style')).not.toMatch(/transition.*?:\s*none/); - })); - - it("should not place a hard block when a class-based CSS transition is run", - inject(function($animate, $rootScope, $compile, $sniffer) { - - if (!$sniffer.transitions) return; - - ss.addRule('.my-class', '-webkit-transition:5s linear all;' + - 'transition:5s linear all;'); - - element = $compile(html('
1
'))($rootScope); - - $animate.addClass(element, 'my-class'); - $rootScope.$digest(); - - expect(element.attr('style')).not.toMatch(/transition.*?:\s*none/); - expect(element.hasClass('my-class')).toBe(false); - expect(element.hasClass('my-class-add')).toBe(true); - - $animate.triggerReflow(); - $rootScope.$digest(); - - expect(element.attr('style')).not.toMatch(/transition.*?:\s*none/); - expect(element.hasClass('my-class')).toBe(true); - expect(element.hasClass('my-class-add')).toBe(true); - expect(element.hasClass('my-class-add-active')).toBe(true); - })); - - it("should stagger the items when the correct CSS class is provided", - inject(function($animate, $rootScope, $compile, $sniffer, $timeout, $document, $rootElement, $browser) { - - if (!$sniffer.transitions) return; - - $animate.enabled(true); - - ss.addRule('.real-animation.ng-enter, .real-animation.ng-leave, .real-animation-fake.ng-enter, .real-animation-fake.ng-leave', - '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); - - ss.addRule('.real-animation.ng-enter-stagger, .real-animation.ng-leave-stagger', - '-webkit-transition-delay:0.1s;' + - '-webkit-transition-duration:0s;' + - 'transition-delay:0.1s;' + - 'transition-duration:0s;'); - - ss.addRule('.fake-animation.ng-enter-stagger, .fake-animation.ng-leave-stagger', - '-webkit-transition-delay:0.1s;' + - '-webkit-transition-duration:1s;' + - 'transition-delay:0.1s;' + - 'transition-duration:1s;'); - - var container = $compile(html('
'))($rootScope); - - var newScope, element, elements = []; - for (var i = 0; i < 5; i++) { - newScope = $rootScope.$new(); - element = $compile('
')(newScope); - $animate.enter(element, container); - elements.push(element); - } - - $rootScope.$digest(); - $animate.triggerReflow(); - - expect($browser.deferredFns.length).toEqual(5); //4 staggers + 1 combined timeout - $timeout.flush(); - - for (i = 0; i < 5; i++) { - dealoc(elements[i]); - newScope = $rootScope.$new(); - element = $compile('
')(newScope); - $animate.enter(element, container); - elements[i] = element; - } - - $rootScope.$digest(); - $animate.triggerReflow(); - - expect($browser.deferredFns.length).toEqual(0); //no animation was triggered - })); - - - it("should stagger items when multiple transition durations/delays are defined", - inject(function($animate, $rootScope, $compile, $sniffer, $timeout, $document, $rootElement, $window) { - - if (!$sniffer.transitions) return; - - $animate.enabled(true); - - ss.addRule('.stagger-animation.ng-enter, .ani.ng-leave', - '-webkit-transition:1s linear color 2s, 3s linear font-size 4s;' + - 'transition:1s linear color 2s, 3s linear font-size 4s;'); - - ss.addRule('.stagger-animation.ng-enter-stagger, .ani.ng-leave-stagger', - '-webkit-transition-delay:0.1s;' + - 'transition-delay:0.1s;'); - - var container = $compile(html('
'))($rootScope); - - var elements = []; - for (var i = 0; i < 4; i++) { - var newScope = $rootScope.$new(); - var element = $compile('
')(newScope); - $animate.enter(element, container); - elements.push(element); - } - - $rootScope.$digest(); - $animate.triggerReflow(); - - for (i = 1; i < 4; i++) { - expect(elements[i]).not.toHaveClass('ng-enter-active'); - expect(elements[i]).toHaveClass('ng-enter-pending'); - expect(getMaxValue('transitionDelay', elements[i], $window)).toBe(4); - } - - $timeout.flush(300); - - for (i = 1; i < 4; i++) { - expect(elements[i]).toHaveClass('ng-enter-active'); - expect(elements[i]).not.toHaveClass('ng-enter-pending'); - expect(getMaxValue('transitionDelay', elements[i], $window)).toBe(4); - } - })); - - it("should stagger items, apply directive styles but not apply a transition style when the stagger step kicks in", - inject(function($animate, $rootScope, $compile, $sniffer, $timeout, $document, $rootElement, $window) { - - if (!$sniffer.transitions) return; - - $animate.enabled(true); - - ss.addRule('.stagger-animation.ng-enter, .ani.ng-leave', - '-webkit-transition:1s linear color 2s, 3s linear font-size 4s;' + - 'transition:1s linear color 2s, 3s linear font-size 4s;'); - - ss.addRule('.stagger-animation.ng-enter-stagger, .ani.ng-leave-stagger', - '-webkit-transition-delay:0.1s;' + - 'transition-delay:0.1s;'); - - var styles = { - from: { left: '155px' }, - to: { left: '255px' } - }; - var container = $compile(html('
'))($rootScope); - - var elements = []; - for (var i = 0; i < 4; i++) { - var newScope = $rootScope.$new(); - var element = $compile('
')(newScope); - $animate.enter(element, container, null, styles); - elements.push(element); - } - - $rootScope.$digest(); - - for (i = 0; i < 4; i++) { - expect(elements[i]).toHaveClass('ng-enter'); - assertLeftStyle(elements[i], '155'); - } - - $animate.triggerReflow(); - - expect(elements[0]).toHaveClass('ng-enter-active'); - assertLeftStyle(elements[0], '255'); - assertNoTransitionDuration(elements[0]); - - for (i = 1; i < 4; i++) { - expect(elements[i]).not.toHaveClass('ng-enter-active'); - assertLeftStyle(elements[i], '255', true); - } - - $timeout.flush(300); - - for (i = 1; i < 4; i++) { - expect(elements[i]).toHaveClass('ng-enter-active'); - assertNoTransitionDuration(elements[i]); - assertLeftStyle(elements[i], '255'); - } - - $timeout.flush(); - - for (i = 0; i < 4; i++) { - expect(elements[i]).not.toHaveClass('ng-enter'); - expect(elements[i]).not.toHaveClass('ng-enter-active'); - assertNoTransitionDuration(elements[i]); - assertLeftStyle(elements[i], '255'); - } - - function assertLeftStyle(element, val, not) { - var regex = new RegExp('left: ' + val + 'px'); - var style = element.attr('style'); - not ? expect(style).not.toMatch(regex) - : expect(style).toMatch(regex); - } - - function assertNoTransitionDuration(element) { - var style = element.attr('style'); - expect(style).not.toMatch(/transition/); - } - })); - - it("should apply a closing timeout to close all pending transitions", - inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { - - if (!$sniffer.transitions) return; - - ss.addRule('.animated-element', '-webkit-transition:5s linear all;' + - 'transition:5s linear all;'); - - element = $compile(html('
foo
'))($rootScope); - - $animate.addClass(element, 'some-class'); - $rootScope.$digest(); - - $animate.triggerReflow(); //reflow - expect(element.hasClass('some-class-add-active')).toBe(true); - - $timeout.flush(7500); //closing timeout - expect(element.hasClass('some-class-add-active')).toBe(false); - })); - - it("should intelligently cancel former timeouts and close off a series of elements a final timeout", function() { - var currentTimestamp, cancellations = 0; - module(function($provide) { - $provide.decorator('$timeout', function($delegate) { - var _cancel = $delegate.cancel; - $delegate.cancel = function(timer) { - if (timer) { - cancellations++; - return _cancel.apply($delegate, arguments); - } - }; - return $delegate; - }); - - return function($sniffer) { - if ($sniffer.transitions) { - currentTimestamp = Date.now(); - spyOn(Date,'now').andCallFake(function() { - return currentTimestamp; - }); - } - }; - }); - inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { - if (!$sniffer.transitions) return; - - ss.addRule('.animate-me div', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); - - ss.addRule('.animate-me-longer div', '-webkit-transition:1.5s linear all;' + - 'transition:1.5s linear all;'); - - element = $compile(html('
' + - '
' + - '
'))($rootScope); - $rootScope.items = [0]; - $rootScope.$digest(); - $animate.triggerReflow(); - - currentTimestamp += 2250; //1.5 * 1500 = 2250 - - element[0].className = 'animate-me'; - - $rootScope.items = [1,2,3,4,5,6,7,8,9,10]; - - $rootScope.$digest(); - - $rootScope.items = [0]; - $animate.triggerReflow(); - - currentTimestamp += 1500; //1.5 * 1000 = 1500 - $timeout.flush(1500); - - expect(cancellations).toBe(1); - expect(element.children().length).toBe(10); - cancellations = 0; - - $rootScope.items = [1]; - $rootScope.$digest(); - - $animate.triggerReflow(); - $timeout.flush(1500); - expect(element.children().length).toBe(1); - expect(cancellations).toBe(1); - }); - }); - - it('should apply a closing timeout to close all parallel class-based animations on the same element', - inject(function($sniffer, $compile, $rootScope, $rootElement, $animate, $timeout) { - - if (!$sniffer.transitions) return; - - ss.addRule('.base-class', '-webkit-transition:2s linear all;' + - 'transition:2s linear all;'); - - var element = $compile('
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - $animate.addClass(element, 'one'); - $animate.addClass(element, 'two'); - - $animate.triggerReflow(); - - $timeout.flush(3000); //2s * 1.5 - - expect(element.hasClass('one-add')).toBeFalsy(); - expect(element.hasClass('one-add-active')).toBeFalsy(); - expect(element.hasClass('two-add')).toBeFalsy(); - expect(element.hasClass('two-add-active')).toBeFalsy(); - expect(element.hasClass('ng-animate')).toBeFalsy(); - })); - - it("apply a closing timeout with respect to a staggering animation", - inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { - - if (!$sniffer.transitions) return; - - ss.addRule('.entering-element.ng-enter', - '-webkit-transition:5s linear all;' + - 'transition:5s linear all;'); - - ss.addRule('.entering-element.ng-enter-stagger', - '-webkit-transition-delay:0.5s;' + - 'transition-delay:0.5s;'); - - element = $compile(html('
'))($rootScope); - var kids = []; - for (var i = 0; i < 5; i++) { - kids.push(angular.element('
')); - $animate.enter(kids[i], element); - } - $rootScope.$digest(); - - $animate.triggerReflow(); //reflow - expect(element.children().length).toBe(5); - - for (i = 1; i < 5; i++) { - expect(kids[i]).not.toHaveClass('ng-enter-active'); - expect(kids[i]).toHaveClass('ng-enter-pending'); - } - - $timeout.flush(2000); - - for (i = 1; i < 5; i++) { - expect(kids[i]).toHaveClass('ng-enter-active'); - expect(kids[i]).not.toHaveClass('ng-enter-pending'); - } - - //(stagger * index) + (duration + delay) * 150% - //0.5 * 4 + 5 * 1.5 = 9500; - //9500 - 2000 - 7499 = 1 - $timeout.flush(7499); - - for (i = 0; i < 5; i++) { - expect(kids[i].hasClass('ng-enter-active')).toBe(true); - } - - $timeout.flush(1); //up to 2000ms - - for (i = 0; i < 5; i++) { - expect(kids[i].hasClass('ng-enter-active')).toBe(false); - } - })); - - it("should cancel all the existing stagger timers when the animation is cancelled", - inject(function($animate, $rootScope, $compile, $sniffer, $timeout, $browser) { - - if (!$sniffer.transitions) return; - - ss.addRule('.entering-element.ng-enter', - '-webkit-transition:5s linear all;' + - 'transition:5s linear all;'); - - ss.addRule('.entering-element.ng-enter-stagger', - '-webkit-transition-delay:1s;' + - 'transition-delay:1s;'); - - var cancellations = []; - element = $compile(html('
'))($rootScope); - var kids = []; - for (var i = 0; i < 5; i++) { - kids.push(angular.element('
')); - cancellations.push($animate.enter(kids[i], element)); - } - $rootScope.$digest(); - - $animate.triggerReflow(); //reflow - expect(element.children().length).toBe(5); - - for (i = 1; i < 5; i++) { - expect(kids[i]).not.toHaveClass('ng-enter-active'); - expect(kids[i]).toHaveClass('ng-enter-pending'); - } - - expect($browser.deferredFns.length).toEqual(5); //4 staggers + 1 combined timeout - - forEach(cancellations, function(promise) { - $animate.cancel(promise); - }); - - for (i = 1; i < 5; i++) { - expect(kids[i]).not.toHaveClass('ng-enter'); - expect(kids[i]).not.toHaveClass('ng-enter-active'); - expect(kids[i]).not.toHaveClass('ng-enter-pending'); - } - - //the staggers are gone, but the global timeout remains - expect($browser.deferredFns.length).toEqual(1); - })); - - - it("should not allow the closing animation to close off a successive animation midway", - inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { - - if (!$sniffer.transitions) return; - - ss.addRule('.some-class-add', '-webkit-transition:5s linear all;' + - 'transition:5s linear all;'); - ss.addRule('.some-class-remove', '-webkit-transition:10s linear all;' + - 'transition:10s linear all;'); - - element = $compile(html('
foo
'))($rootScope); - - $animate.addClass(element, 'some-class'); - $rootScope.$digest(); - - $animate.triggerReflow(); //reflow - expect(element.hasClass('some-class-add-active')).toBe(true); - - $animate.removeClass(element, 'some-class'); - $rootScope.$digest(); - - $animate.triggerReflow(); //second reflow - - $timeout.flush(7500); //closing timeout for the first animation - expect(element.hasClass('some-class-remove-active')).toBe(true); - - $timeout.flush(15000); //closing timeout for the second animation - expect(element.hasClass('some-class-remove-active')).toBe(false); - - $timeout.verifyNoPendingTasks(); - })); - }); - - - it("should apply staggering to both transitions and keyframe animations when used within the same animation", - inject(function($animate, $rootScope, $compile, $sniffer, $timeout, $document, $rootElement, $browser) { - - if (!$sniffer.transitions) return; - - $animate.enabled(true); - - ss.addRule('.stagger-animation.ng-enter, .stagger-animation.ng-leave', - '-webkit-animation:my_animation 1s 1s, your_animation 1s 2s;' + - 'animation:my_animation 1s 1s, your_animation 1s 2s;' + - '-webkit-transition:1s linear all 1s;' + - 'transition:1s linear all 1s;'); - - ss.addRule('.stagger-animation.ng-enter-stagger, .stagger-animation.ng-leave-stagger', - '-webkit-transition-delay:0.1s;' + - 'transition-delay:0.1s;' + - '-webkit-animation-delay:0.2s;' + - 'animation-delay:0.2s;'); - - var container = $compile(html('
'))($rootScope); - - var elements = []; - for (var i = 0; i < 3; i++) { - var newScope = $rootScope.$new(); - var element = $compile('
')(newScope); - $animate.enter(element, container); - elements.push(element); - } - - $rootScope.$digest(); - $animate.triggerReflow(); - expect($browser.deferredFns.length).toEqual(3); //2 staggers + 1 combined timeout - - expect(elements[0].attr('style')).toBeFalsy(); - expect(elements[1].attr('style')).toMatch(/animation-play-state:\s*paused/); - expect(elements[2].attr('style')).toMatch(/animation-play-state:\s*paused/); - - for (i = 1; i < 3; i++) { - expect(elements[i]).not.toHaveClass('ng-enter-active'); - expect(elements[i]).toHaveClass('ng-enter-pending'); - } - - $timeout.flush(0.4 * 1000); - - for (i = 1; i < 3; i++) { - expect(elements[i]).toHaveClass('ng-enter-active'); - expect(elements[i]).not.toHaveClass('ng-enter-pending'); - } - - for (i = 0; i < 3; i++) { - browserTrigger(elements[i],'transitionend', { timeStamp: Date.now() + 22000, elapsedTime: 22000 }); - expect(elements[i].attr('style')).toBeFalsy(); - } - })); - - it("should create a piggy-back-transition which has a duration the same as the max keyframe duration if any directive styles are provided", - inject(function($compile, $animate, $rootScope, $sniffer) { - - $animate.enabled(true); - ss.addRule('.on', '-webkit-transition: 1s linear all; transition: 1s linear all;'); - - element = $compile(html('
1
'))($rootScope); - - $animate.addClass(element, 'on', { - to: {color: 'red'} - }); - - $rootScope.$digest(); - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(element.attr('style')).toContain('color: red'); - expect(element.attr('style')).not.toContain('transition'); - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } - - expect(element.attr('style')).toContain('color: red'); - })); - }); - - - describe('animation evaluation', function() { - - it('should re-evaluate the CSS classes for an animation each time', - inject(function($animate, $rootScope, $sniffer, $rootElement, $timeout, $compile) { - - ss.addRule('.abc.ng-enter', '-webkit-transition:22s linear all;' + - 'transition:22s linear all;'); - ss.addRule('.xyz.ng-enter', '-webkit-transition:11s linear all;' + - 'transition:11s linear all;'); - - var parent = $compile('
')($rootScope); - var element = parent.find('span'); - $rootElement.append(parent); - angular.element(document.body).append($rootElement); - - $rootScope.klass = 'abc'; - $animate.enter(element, parent); - $rootScope.$digest(); - - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(element.hasClass('abc')).toBe(true); - expect(element.hasClass('ng-enter')).toBe(true); - expect(element.hasClass('ng-enter-active')).toBe(true); - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 22000, elapsedTime: 22 }); - $animate.triggerCallbackPromise(); - } - expect(element.hasClass('abc')).toBe(true); - - $rootScope.klass = 'xyz'; - $animate.enter(element, parent); - $rootScope.$digest(); - - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(element.hasClass('xyz')).toBe(true); - expect(element.hasClass('ng-enter')).toBe(true); - expect(element.hasClass('ng-enter-active')).toBe(true); - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 11000, elapsedTime: 11 }); - $animate.triggerCallbackPromise(); - } - expect(element.hasClass('xyz')).toBe(true); - })); - - - it('should only append active to the newly append CSS className values', - inject(function($animate, $rootScope, $sniffer, $rootElement) { - - ss.addRule('.ng-enter', '-webkit-transition:9s linear all;' + - 'transition:9s linear all;'); - - var parent = jqLite('
'); - var element = parent.find('span'); - $rootElement.append(parent); - angular.element(document.body).append($rootElement); - - element.attr('class','one two'); - - $animate.enter(element, parent); - $rootScope.$digest(); - - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(element.hasClass('one')).toBe(true); - expect(element.hasClass('two')).toBe(true); - expect(element.hasClass('ng-enter')).toBe(true); - expect(element.hasClass('ng-enter-active')).toBe(true); - expect(element.hasClass('one-active')).toBe(false); - expect(element.hasClass('two-active')).toBe(false); - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 3000, elapsedTime: 3 }); - } - - expect(element.hasClass('one')).toBe(true); - expect(element.hasClass('two')).toBe(true); - })); - }); - - - describe("Callbacks", function() { - - beforeEach(function() { - module(function($animateProvider) { - $animateProvider.register('.custom', function($timeout) { - return { - removeClass: function(element, className, done) { - $timeout(done, 2000); - } - }; - }); - $animateProvider.register('.other', function($timeout) { - return { - enter: function(element, done) { - $timeout(done, 10000); - } - }; - }); - }); - }); - - - it("should fire the enter callback", - inject(function($animate, $rootScope, $compile, $sniffer, $rootElement) { - - var parent = jqLite('
'); - var element = parent.find('span'); - $rootElement.append(parent); - body.append($rootElement); - - var flag = false; - $animate.enter(element, parent, null).then(function() { - flag = true; - }); - $rootScope.$digest(); - - $animate.triggerCallbackPromise(); - - expect(flag).toBe(true); - })); - - - it("should fire the leave callback", - inject(function($animate, $rootScope, $compile, $sniffer, $rootElement) { - - var parent = jqLite('
'); - var element = parent.find('span'); - $rootElement.append(parent); - body.append($rootElement); - - var flag = false; - $animate.leave(element).then(function() { - flag = true; - }); - $rootScope.$digest(); - - $animate.triggerCallbackPromise(); - - expect(flag).toBe(true); - })); - - - it("should fire the move callback", - inject(function($animate, $rootScope, $compile, $sniffer, $rootElement) { - - var parent = jqLite('
'); - var parent2 = jqLite('
'); - var element = parent.find('span'); - $rootElement.append(parent); - body.append($rootElement); - - var flag = false; - $animate.move(element, parent, parent2).then(function() { - flag = true; - }); - $rootScope.$digest(); - - $animate.triggerCallbackPromise(); - - expect(flag).toBe(true); - expect(element.parent().id).toBe(parent2.id); - - dealoc(element); - })); - - - it("should fire the addClass/removeClass callbacks", - inject(function($animate, $rootScope, $compile, $sniffer, $rootElement) { - - var parent = jqLite('
'); - var element = parent.find('span'); - $rootElement.append(parent); - body.append($rootElement); - - var signature = ''; - $animate.addClass(element, 'on').then(function() { - signature += 'A'; - }); - $rootScope.$digest(); - $animate.triggerReflow(); - - $animate.removeClass(element, 'on').then(function() { - signature += 'B'; - }); - $rootScope.$digest(); - $animate.triggerReflow(); - - $animate.triggerCallbackPromise(); - - expect(signature).toBe('AB'); - })); - - it("should fire the setClass callback", - inject(function($animate, $rootScope, $compile, $sniffer, $rootElement) { - - var parent = jqLite('
'); - var element = parent.find('span'); - $rootElement.append(parent); - body.append($rootElement); - - expect(element.hasClass('on')).toBe(false); - expect(element.hasClass('off')).toBe(true); - - var signature = ''; - $animate.setClass(element, 'on', 'off').then(function() { - signature += 'Z'; - }); - $rootScope.$digest(); - - $animate.triggerReflow(); - $animate.triggerCallbackPromise(); - - expect(signature).toBe('Z'); - expect(element.hasClass('on')).toBe(true); - expect(element.hasClass('off')).toBe(false); - })); - - it('should fire DOM callbacks on the element being animated', - inject(function($animate, $rootScope, $compile, $sniffer, $rootElement) { - - if (!$sniffer.transitions) return; - - $animate.enabled(true); - - ss.addRule('.klass-add', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); - - var element = jqLite('
'); - $rootElement.append(element); - body.append($rootElement); - - var steps = []; - element.on('$animate:before', function(e, data) { - steps.push(['before', data.className, data.event]); - }); - - element.on('$animate:after', function(e, data) { - steps.push(['after', data.className, data.event]); - }); - - element.on('$animate:close', function(e, data) { - steps.push(['close', data.className, data.event]); - }); - - $animate.addClass(element, 'klass').then(function() { - steps.push(['done', 'klass', 'addClass']); - }); - $rootScope.$digest(); - - $animate.triggerCallbackEvents(); - - expect(steps.pop()).toEqual(['before', 'klass', 'addClass']); - - $animate.triggerReflow(); - - $animate.triggerCallbackEvents(); - - expect(steps.pop()).toEqual(['after', 'klass', 'addClass']); - - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - - $animate.triggerCallbackEvents(); - - expect(steps.shift()).toEqual(['close', 'klass', 'addClass']); - - $animate.triggerCallbackPromise(); - - expect(steps.shift()).toEqual(['done', 'klass', 'addClass']); - })); - - it('should fire the DOM callbacks even if no animation is rendered', - inject(function($animate, $rootScope, $compile, $sniffer, $rootElement) { - - $animate.enabled(true); - - var parent = jqLite('
'); - var element = jqLite('
'); - $rootElement.append(parent); - body.append($rootElement); - - var steps = []; - element.on('$animate:before', function(e, data) { - steps.push(['before', data.className, data.event]); - }); - - element.on('$animate:after', function(e, data) { - steps.push(['after', data.className, data.event]); - }); - - $animate.enter(element, parent); - $rootScope.$digest(); - - $animate.triggerCallbackEvents(); - - expect(steps.shift()).toEqual(['before', 'ng-enter', 'enter']); - expect(steps.shift()).toEqual(['after', 'ng-enter', 'enter']); - })); - - it('should not fire DOM callbacks on the element being animated unless registered', - inject(function($animate, $rootScope, $compile, $sniffer, $rootElement, $timeout) { - - $animate.enabled(true); - - var element = jqLite('
'); - $rootElement.append(element); - body.append($rootElement); - - $animate.addClass(element, 'class'); - $rootScope.$digest(); - - $timeout.verifyNoPendingTasks(); - })); - - it("should fire a done callback when provided with no animation", - inject(function($animate, $rootScope, $compile, $sniffer, $rootElement) { - - var parent = jqLite('
'); - var element = parent.find('span'); - $rootElement.append(parent); - body.append($rootElement); - - var flag = false; - $animate.removeClass(element, 'ng-hide').then(function() { - flag = true; - }); - $rootScope.$digest(); - - $animate.triggerCallbackPromise(); - expect(flag).toBe(true); - })); - - - it("should fire a done callback when provided with a css animation/transition", - inject(function($animate, $rootScope, $compile, $sniffer, $rootElement) { - - ss.addRule('.ng-hide-add', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); - ss.addRule('.ng-hide-remove', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); - - var parent = jqLite('
'); - $rootElement.append(parent); - body.append($rootElement); - var element = parent.find('span'); - - var flag = false; - $animate.addClass(element, 'ng-hide').then(function() { - flag = true; - }); - $rootScope.$digest(); - - if ($sniffer.transitions) { - $animate.triggerReflow(); - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } - $animate.triggerCallbackPromise(); - expect(flag).toBe(true); - })); - - - it("should fire a done callback when provided with a JS animation", - inject(function($animate, $rootScope, $compile, $sniffer, $rootElement) { - - var parent = jqLite('
'); - $rootElement.append(parent); - body.append($rootElement); - var element = parent.find('span'); - element.addClass('custom'); - - var flag = false; - $animate.removeClass(element, 'ng-hide').then(function() { - flag = true; - }); - $rootScope.$digest(); - - $animate.triggerCallbackPromise(); - expect(flag).toBe(true); - })); - - - it("should fire the callback right away if another animation is called right after", - inject(function($animate, $rootScope, $compile, $sniffer, $rootElement) { - - ss.addRule('.ng-hide-add', '-webkit-transition:9s linear all;' + - 'transition:9s linear all;'); - ss.addRule('.ng-hide-remove', '-webkit-transition:9s linear all;' + - 'transition:9s linear all;'); - - var parent = jqLite('
'); - $rootElement.append(parent); - body.append($rootElement); - var element = parent.find('span'); - - var signature = ''; - $animate.removeClass(element, 'ng-hide').then(function() { - signature += 'A'; - }); - $rootScope.$digest(); - $animate.addClass(element, 'ng-hide').then(function() { - signature += 'B'; - }); - $rootScope.$digest(); - - $animate.addClass(element, 'ng-hide'); //earlier animation cancelled - if ($sniffer.transitions) { - $animate.triggerReflow(); - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 9 }); - } - $animate.triggerCallbackPromise(); - expect(signature).toBe('AB'); - })); - }); - - describe("options", function() { - - it('should add and remove the temporary className value is provided', function() { - var captures = {}; - module(function($animateProvider) { - $animateProvider.register('.capture', function() { - return { - enter: capture('enter'), - leave: capture('leave'), - move: capture('move'), - addClass: capture('addClass'), - removeClass: capture('removeClass'), - setClass: capture('setClass') - }; - - function capture(event) { - return function(element, add, remove, styles, done) { - //some animations only have one extra param - done = arguments[arguments.length - 2]; //the last one is the styles array - captures[event]=done; - }; - } - }); - }); - inject(function($animate, $rootScope, $compile, $rootElement, $document) { - var container = jqLite('
'); - var container2 = jqLite('
'); - var element = jqLite('
'); - $rootElement.append(container); - $rootElement.append(container2); - angular.element($document[0].body).append($rootElement); - - $compile(element)($rootScope); - - assertTempClass('enter', 'temp-enter', function() { - $animate.enter(element, container, null, { - tempClasses: 'temp-enter' - }); - }); - - assertTempClass('move', 'temp-move', function() { - $animate.move(element, null, container2, { - tempClasses: 'temp-move' - }); - }); - - assertTempClass('addClass', 'temp-add', function() { - $animate.addClass(element, 'add', { - tempClasses: 'temp-add' - }); - }); - - assertTempClass('removeClass', 'temp-remove', function() { - $animate.removeClass(element, 'add', { - tempClasses: 'temp-remove' - }); - }); - - element.addClass('remove'); - assertTempClass('setClass', 'temp-set', function() { - $animate.setClass(element, 'add', 'remove', { - tempClasses: 'temp-set' - }); - }); - - assertTempClass('leave', 'temp-leave', function() { - $animate.leave(element, { - tempClasses: 'temp-leave' - }); - }); - - function assertTempClass(event, className, animationOperation) { - expect(element).not.toHaveClass(className); - animationOperation(); - $rootScope.$digest(); - expect(element).toHaveClass(className); - $animate.triggerReflow(); - captures[event](); - $animate.triggerCallbacks(); - expect(element).not.toHaveClass(className); - } - }); - }); - }); - - describe("addClass / removeClass", function() { - - var captured; - beforeEach(function() { - module(function($animateProvider) { - $animateProvider.register('.klassy', function($timeout) { - return { - addClass: function(element, className, done) { - captured = 'addClass-' + className; - $timeout(done, 500, false); - }, - removeClass: function(element, className, done) { - captured = 'removeClass-' + className; - $timeout(done, 3000, false); - } - }; - }); - }); - }); - - - it("should not perform an animation, and the followup DOM operation, if the class is " + - "already present during addClass or not present during removeClass on the element", - inject(function($animate, $rootScope, $sniffer, $rootElement) { - - var element = jqLite('
'); - $rootElement.append(element); - body.append($rootElement); - - //skipped animations - captured = 'none'; - $animate.removeClass(element, 'some-class'); - $rootScope.$digest(); - expect(element.hasClass('some-class')).toBe(false); - expect(captured).toBe('none'); - - element.addClass('some-class'); - - captured = 'nothing'; - $animate.addClass(element, 'some-class'); - $rootScope.$digest(); - expect(captured).toBe('nothing'); - expect(element.hasClass('some-class')).toBe(true); - - //actual animations - captured = 'none'; - $animate.removeClass(element, 'some-class'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(element.hasClass('some-class')).toBe(false); - expect(captured).toBe('removeClass-some-class'); - - captured = 'nothing'; - $animate.addClass(element, 'some-class'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(element.hasClass('some-class')).toBe(true); - expect(captured).toBe('addClass-some-class'); - })); - - it("should perform the animation if passed native dom element", - inject(function($animate, $rootScope, $sniffer, $rootElement) { - - var element = jqLite('
'); - $rootElement.append(element); - body.append($rootElement); - - //skipped animations - captured = 'none'; - $animate.removeClass(element[0], 'some-class'); - $rootScope.$digest(); - expect(element.hasClass('some-class')).toBe(false); - expect(captured).toBe('none'); - - element.addClass('some-class'); - - captured = 'nothing'; - $animate.addClass(element[0], 'some-class'); - $rootScope.$digest(); - expect(captured).toBe('nothing'); - expect(element.hasClass('some-class')).toBe(true); - - //actual animations - captured = 'none'; - $animate.removeClass(element[0], 'some-class'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(element.hasClass('some-class')).toBe(false); - expect(captured).toBe('removeClass-some-class'); - - captured = 'nothing'; - $animate.addClass(element[0], 'some-class'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(element.hasClass('some-class')).toBe(true); - expect(captured).toBe('addClass-some-class'); - })); - - it("should add and remove CSS classes after an animation even if no animation is present", - inject(function($animate, $rootScope, $sniffer, $rootElement) { - - var parent = jqLite('
'); - $rootElement.append(parent); - body.append($rootElement); - var element = jqLite(parent.find('span')); - - $animate.addClass(element,'klass'); - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(element.hasClass('klass')).toBe(true); - - $animate.removeClass(element,'klass'); - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(element.hasClass('klass')).toBe(false); - expect(element.hasClass('klass-remove')).toBe(false); - expect(element.hasClass('klass-remove-active')).toBe(false); - })); - - - it("should add and remove CSS classes with a callback", - inject(function($animate, $rootScope, $sniffer, $rootElement) { - - var parent = jqLite('
'); - $rootElement.append(parent); - body.append($rootElement); - var element = jqLite(parent.find('span')); - - var signature = ''; - - $animate.addClass(element,'klass').then(function() { - signature += 'A'; - }); - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(element.hasClass('klass')).toBe(true); - - $animate.removeClass(element,'klass').then(function() { - signature += 'B'; - }); - $rootScope.$digest(); - $animate.triggerReflow(); - - $animate.triggerCallbackPromise(); - expect(element.hasClass('klass')).toBe(false); - expect(signature).toBe('AB'); - })); - - - it("should end the current addClass animation, add the CSS class and then run the removeClass animation", - inject(function($animate, $rootScope, $sniffer, $rootElement) { - - ss.addRule('.klass-add', '-webkit-transition:3s linear all;' + - 'transition:3s linear all;'); - ss.addRule('.klass-remove', '-webkit-transition:3s linear all;' + - 'transition:3s linear all;'); - - var parent = jqLite('
'); - $rootElement.append(parent); - body.append($rootElement); - var element = jqLite(parent.find('span')); - - var signature = ''; - - $animate.addClass(element,'klass').then(function() { - signature += '1'; - }); - $rootScope.$digest(); - - if ($sniffer.transitions) { - expect(element.hasClass('klass-add')).toBe(true); - $animate.triggerReflow(); - expect(element.hasClass('klass')).toBe(true); - expect(element.hasClass('klass-add-active')).toBe(true); - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 3000, elapsedTime: 3 }); - } - - $animate.triggerCallbackPromise(); - - //this cancels out the older animation - $animate.removeClass(element,'klass').then(function() { - signature += '2'; - }); - $rootScope.$digest(); - - if ($sniffer.transitions) { - expect(element.hasClass('klass-remove')).toBe(true); - - $animate.triggerReflow(); - expect(element.hasClass('klass')).toBe(false); - expect(element.hasClass('klass-add')).toBe(false); - expect(element.hasClass('klass-add-active')).toBe(false); - - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 3000, elapsedTime: 3 }); - } - - $animate.triggerCallbackPromise(); - - expect(element.hasClass('klass')).toBe(false); - expect(signature).toBe('12'); - })); - - - it("should properly execute JS animations and use callbacks when using addClass / removeClass", - inject(function($animate, $rootScope, $sniffer, $rootElement, $timeout) { - - var parent = jqLite('
'); - $rootElement.append(parent); - body.append($rootElement); - var element = jqLite(parent.find('span')); - - var signature = ''; - - $animate.addClass(element,'klassy').then(function() { - signature += 'X'; - }); - $rootScope.$digest(); - $animate.triggerReflow(); - - $timeout.flush(500); - - expect(element.hasClass('klassy')).toBe(true); - - $animate.removeClass(element,'klassy').then(function() { - signature += 'Y'; - }); - $rootScope.$digest(); - $animate.triggerReflow(); - - $timeout.flush(3000); - - expect(element.hasClass('klassy')).toBe(false); - - $animate.triggerCallbackPromise(); - expect(signature).toBe('XY'); - })); - - it("should properly execute JS animations if passed native dom element", - inject(function($animate, $rootScope, $sniffer, $rootElement, $timeout) { - - var parent = jqLite('
'); - $rootElement.append(parent); - body.append($rootElement); - var element = jqLite(parent.find('span')); - - var signature = ''; - - $animate.addClass(element[0],'klassy').then(function() { - signature += 'X'; - }); - $rootScope.$digest(); - $animate.triggerReflow(); - - $timeout.flush(500); - - expect(element.hasClass('klassy')).toBe(true); - - $animate.removeClass(element[0],'klassy').then(function() { - signature += 'Y'; - }); - $rootScope.$digest(); - $animate.triggerReflow(); - - $timeout.flush(3000); - - expect(element.hasClass('klassy')).toBe(false); - - $animate.triggerCallbackPromise(); - expect(signature).toBe('XY'); - })); - - it("should properly execute CSS animations/transitions and use callbacks when using addClass / removeClass", - inject(function($animate, $rootScope, $sniffer, $rootElement) { - - ss.addRule('.klass-add', '-webkit-transition:11s linear all;' + - 'transition:11s linear all;'); - ss.addRule('.klass-remove', '-webkit-transition:11s linear all;' + - 'transition:11s linear all;'); - - var parent = jqLite('
'); - $rootElement.append(parent); - body.append($rootElement); - var element = jqLite(parent.find('span')); - - var signature = ''; - - $animate.addClass(element,'klass').then(function() { - signature += 'd'; - }); - $rootScope.$digest(); - - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(element.hasClass('klass-add')).toBe(true); - expect(element.hasClass('klass-add-active')).toBe(true); - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 11000, elapsedTime: 11 }); - expect(element.hasClass('klass-add')).toBe(false); - expect(element.hasClass('klass-add-active')).toBe(false); - } - - $animate.triggerCallbackPromise(); - expect(element.hasClass('klass')).toBe(true); - - $animate.removeClass(element,'klass').then(function() { - signature += 'b'; - }); - $rootScope.$digest(); - - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(element.hasClass('klass-remove')).toBe(true); - expect(element.hasClass('klass-remove-active')).toBe(true); - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 11000, elapsedTime: 11 }); - expect(element.hasClass('klass-remove')).toBe(false); - expect(element.hasClass('klass-remove-active')).toBe(false); - } - - $animate.triggerCallbackPromise(); - expect(element.hasClass('klass')).toBe(false); - - expect(signature).toBe('db'); - })); - - - it("should allow for multiple css classes to be animated plus a callback when added", - inject(function($animate, $rootScope, $sniffer, $rootElement) { - - ss.addRule('.one-add', '-webkit-transition:7s linear all;' + - 'transition:7s linear all;'); - ss.addRule('.two-add', '-webkit-transition:7s linear all;' + - 'transition:7s linear all;'); - - var parent = jqLite('
'); - $rootElement.append(parent); - body.append($rootElement); - var element = jqLite(parent.find('span')); - - var flag = false; - $animate.addClass(element,'one two').then(function() { - flag = true; - }); - - $rootScope.$digest(); - - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(element.hasClass('one-add')).toBe(true); - expect(element.hasClass('two-add')).toBe(true); - - expect(element.hasClass('one-add-active')).toBe(true); - expect(element.hasClass('two-add-active')).toBe(true); - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 7000, elapsedTime: 7 }); - - expect(element.hasClass('one-add')).toBe(false); - expect(element.hasClass('one-add-active')).toBe(false); - expect(element.hasClass('two-add')).toBe(false); - expect(element.hasClass('two-add-active')).toBe(false); - } - - $animate.triggerCallbackPromise(); - - expect(element.hasClass('one')).toBe(true); - expect(element.hasClass('two')).toBe(true); - - expect(flag).toBe(true); - })); - - - it("should allow for multiple css classes to be animated plus a callback when removed", - inject(function($animate, $rootScope, $sniffer, $rootElement) { - - ss.addRule('.one-remove', '-webkit-transition:9s linear all;' + - 'transition:9s linear all;'); - ss.addRule('.two-remove', '-webkit-transition:9s linear all;' + - 'transition:9s linear all;'); - - var parent = jqLite('
'); - $rootElement.append(parent); - body.append($rootElement); - var element = jqLite(parent.find('span')); - - element.addClass('one two'); - expect(element.hasClass('one')).toBe(true); - expect(element.hasClass('two')).toBe(true); - - var flag = false; - $animate.removeClass(element,'one two').then(function() { - flag = true; - }); - $rootScope.$digest(); - - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(element.hasClass('one-remove')).toBe(true); - expect(element.hasClass('two-remove')).toBe(true); - - expect(element.hasClass('one-remove-active')).toBe(true); - expect(element.hasClass('two-remove-active')).toBe(true); - browserTrigger(element,'transitionend', { timeStamp: Date.now() + 9000, elapsedTime: 9 }); - - expect(element.hasClass('one-remove')).toBe(false); - expect(element.hasClass('one-remove-active')).toBe(false); - expect(element.hasClass('two-remove')).toBe(false); - expect(element.hasClass('two-remove-active')).toBe(false); - } - - $animate.triggerCallbackPromise(); - - expect(element.hasClass('one')).toBe(false); - expect(element.hasClass('two')).toBe(false); - - expect(flag).toBe(true); - })); - }); - }); - - var $rootElement, $document; - beforeEach(module(function() { - return function(_$rootElement_, _$document_, $animate) { - $rootElement = _$rootElement_; - $document = _$document_; - $animate.enabled(true); - }; - })); - - function html(element) { - var body = jqLite($document[0].body); - $rootElement.append(element); - body.append($rootElement); - return element; - } - - - it("should properly animate and parse CSS3 transitions", - inject(function($compile, $rootScope, $animate, $sniffer) { - - ss.addRule('.ng-enter', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); - - var element = html($compile('
...
')($rootScope)); - var child = $compile('
...
')($rootScope); - - $animate.enter(child, element); - $rootScope.$digest(); - - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(child.hasClass('ng-enter')).toBe(true); - expect(child.hasClass('ng-enter-active')).toBe(true); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } - - expect(child.hasClass('ng-enter')).toBe(false); - expect(child.hasClass('ng-enter-active')).toBe(false); - })); - - - it("should properly animate and parse CSS3 animations", - inject(function($compile, $rootScope, $animate, $sniffer) { - - ss.addRule('.ng-enter', '-webkit-animation: some_animation 4s linear 1s 2 alternate;' + - 'animation: some_animation 4s linear 1s 2 alternate;'); - - var element = html($compile('
...
')($rootScope)); - var child = $compile('
...
')($rootScope); - - $animate.enter(child, element); - $rootScope.$digest(); - - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(child.hasClass('ng-enter')).toBe(true); - expect(child.hasClass('ng-enter-active')).toBe(true); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 9000, elapsedTime: 9 }); - } - expect(child.hasClass('ng-enter')).toBe(false); - expect(child.hasClass('ng-enter-active')).toBe(false); - })); - - - it("should skip animations if the browser does not support CSS3 transitions and CSS3 animations", - inject(function($compile, $rootScope, $animate, $sniffer) { - - $sniffer.animations = false; - $sniffer.transitions = false; - - ss.addRule('.ng-enter', '-webkit-animation: some_animation 4s linear 1s 2 alternate;' + - 'animation: some_animation 4s linear 1s 2 alternate;'); - - var element = html($compile('
...
')($rootScope)); - var child = $compile('
...
')($rootScope); - - expect(child.hasClass('ng-enter')).toBe(false); - $animate.enter(child, element); - $rootScope.$digest(); - expect(child.hasClass('ng-enter')).toBe(false); - })); - - - it("should run other defined animations inline with CSS3 animations", function() { - module(function($animateProvider) { - $animateProvider.register('.custom', function($timeout) { - return { - enter: function(element, done) { - element.addClass('i-was-animated'); - $timeout(done, 10, false); - } - }; - }); - }); - inject(function($compile, $rootScope, $animate, $sniffer) { - - ss.addRule('.ng-enter', '-webkit-transition: 1s linear all;' + - 'transition: 1s linear all;'); - - var element = html($compile('
...
')($rootScope)); - var child = $compile('
...
')($rootScope); - - expect(child.hasClass('i-was-animated')).toBe(false); - - child.addClass('custom'); - $animate.enter(child, element); - $rootScope.$digest(); - - if ($sniffer.transitions) { - $animate.triggerReflow(); - browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - } - - expect(child.hasClass('i-was-animated')).toBe(true); - }); - }); - - - it("should properly cancel CSS transitions or animations if another animation is fired", function() { - module(function($animateProvider) { - $animateProvider.register('.usurper', function($timeout) { - return { - leave: function(element, done) { - element.addClass('this-is-mine-now'); - $timeout(done, 55, false); - } - }; - }); - }); - inject(function($compile, $rootScope, $animate, $sniffer, $timeout) { - ss.addRule('.ng-enter', '-webkit-transition: 2s linear all;' + - 'transition: 2s linear all;'); - ss.addRule('.ng-leave', '-webkit-transition: 2s linear all;' + - 'transition: 2s linear all;'); - - var element = html($compile('
...
')($rootScope)); - var child = $compile('
...
')($rootScope); - - $animate.enter(child, element); - $rootScope.$digest(); - - //this is added/removed right away otherwise - if ($sniffer.transitions) { - $animate.triggerReflow(); - expect(child.hasClass('ng-enter')).toBe(true); - expect(child.hasClass('ng-enter-active')).toBe(true); - } - - expect(child.hasClass('this-is-mine-now')).toBe(false); - child.addClass('usurper'); - $animate.leave(child); - $rootScope.$digest(); - $animate.triggerCallbackPromise(); - - expect(child.hasClass('ng-enter')).toBe(false); - expect(child.hasClass('ng-enter-active')).toBe(false); - - expect(child.hasClass('usurper')).toBe(true); - expect(child.hasClass('this-is-mine-now')).toBe(true); - - $timeout.flush(55); - }); - }); - - - it("should not perform the active class animation if the animation has been cancelled before the reflow occurs", function() { - inject(function($compile, $rootScope, $animate, $sniffer) { - if (!$sniffer.transitions) return; - - ss.addRule('.animated.ng-enter', '-webkit-transition: 2s linear all;' + - 'transition: 2s linear all;'); - - var element = html($compile('
...
')($rootScope)); - var child = $compile('
...
')($rootScope); - - $animate.enter(child, element); - $rootScope.$digest(); - - expect(child.hasClass('ng-enter')).toBe(true); - - $animate.leave(child); - $rootScope.$digest(); - - $animate.triggerReflow(); - expect(child.hasClass('ng-enter-active')).toBe(false); - }); - }); - - // - // it("should add and remove CSS classes and perform CSS animations during the process", - // inject(function($compile, $rootScope, $animate, $sniffer, $timeout) { - // - // ss.addRule('.on-add', '-webkit-transition: 10s linear all; ' + - // 'transition: 10s linear all;'); - // ss.addRule('.on-remove', '-webkit-transition: 10s linear all; ' + - // 'transition: 10s linear all;'); - // - // var element = html($compile('
')($rootScope)); - // - // expect(element.hasClass('on')).toBe(false); - // - // $animate.addClass(element, 'on'); - // - // if($sniffer.transitions) { - // expect(element.hasClass('on')).toBe(false); - // expect(element.hasClass('on-add')).toBe(true); - // $animate.triggerCallbackPromise(); - // } - // - // $animate.triggerCallbackPromise(); - // - // expect(element.hasClass('on')).toBe(true); - // expect(element.hasClass('on-add')).toBe(false); - // expect(element.hasClass('on-add-active')).toBe(false); - // - // $animate.removeClass(element, 'on'); - // if($sniffer.transitions) { - // expect(element.hasClass('on')).toBe(true); - // expect(element.hasClass('on-remove')).toBe(true); - // $timeout.flush(10000); - // } - // - // $animate.triggerCallbackPromise(); - // expect(element.hasClass('on')).toBe(false); - // expect(element.hasClass('on-remove')).toBe(false); - // expect(element.hasClass('on-remove-active')).toBe(false); - // })); - // - // - // it("should show and hide elements with CSS & JS animations being performed in the process", function() { - // module(function($animateProvider) { - // $animateProvider.register('.displayer', function($timeout) { - // return { - // removeClass : function(element, className, done) { - // element.removeClass('hiding'); - // element.addClass('showing'); - // $timeout(done, 25, false); - // }, - // addClass : function(element, className, done) { - // element.removeClass('showing'); - // element.addClass('hiding'); - // $timeout(done, 555, false); - // } - // } - // }); - // }) - // inject(function($compile, $rootScope, $animate, $sniffer, $timeout) { - // - // ss.addRule('.ng-hide-add', '-webkit-transition: 5s linear all;' + - // 'transition: 5s linear all;'); - // ss.addRule('.ng-hide-remove', '-webkit-transition: 5s linear all;' + - // 'transition: 5s linear all;'); - // - // var element = html($compile('
')($rootScope)); - // - // element.addClass('displayer'); - // - // expect(element).toBeShown(); - // expect(element.hasClass('showing')).toBe(false); - // expect(element.hasClass('hiding')).toBe(false); - // - // $animate.addClass(element, 'ng-hide'); - // - // if($sniffer.transitions) { - // expect(element).toBeShown(); //still showing - // $animate.triggerCallbackPromise(); - // expect(element).toBeShown(); - // $timeout.flush(5555); - // } - // $animate.triggerCallbackPromise(); - // expect(element).toBeHidden(); - // - // expect(element.hasClass('showing')).toBe(false); - // expect(element.hasClass('hiding')).toBe(true); - // $animate.removeClass(element, 'ng-hide'); - // - // if($sniffer.transitions) { - // expect(element).toBeHidden(); - // $animate.triggerCallbackPromise(); - // expect(element).toBeHidden(); - // $timeout.flush(5580); - // } - // $animate.triggerCallbackPromise(); - // expect(element).toBeShown(); - // - // expect(element.hasClass('showing')).toBe(true); - // expect(element.hasClass('hiding')).toBe(false); - // }); - // }); - - - it("should remove all the previous classes when the next animation is applied before a reflow", function() { - var fn, interceptedClass; - module(function($animateProvider) { - $animateProvider.register('.three', function() { - return { - move: function(element, done) { - fn = function() { - done(); - }; - return function() { - interceptedClass = element.attr('class'); - }; - } - }; - }); - }); - inject(function($compile, $rootScope, $animate) { - var parent = html($compile('
')($rootScope)); - var one = $compile('
')($rootScope); - var two = $compile('
')($rootScope); - var three = $compile('
')($rootScope); - - parent.append(one); - parent.append(two); - parent.append(three); - - $animate.move(three, null, two); - $rootScope.$digest(); - - $animate.move(three, null, one); - $rootScope.$digest(); - - //this means that the former animation was cleaned up before the new one starts - expect(interceptedClass.indexOf('ng-animate') >= 0).toBe(false); - }); - }); - - - it("should provide the correct CSS class to the addClass and removeClass callbacks within a JS animation", function() { - module(function($animateProvider) { - $animateProvider.register('.classify', function() { - return { - removeClass: function(element, className, done) { - element.data('classify','remove-' + className); - done(); - }, - addClass: function(element, className, done) { - element.data('classify','add-' + className); - done(); - } - }; - }); - }); - inject(function($compile, $rootScope, $animate) { - var element = html($compile('
')($rootScope)); - - $animate.addClass(element, 'super'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(element.data('classify')).toBe('add-super'); - - $animate.removeClass(element, 'super'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(element.data('classify')).toBe('remove-super'); - - $animate.addClass(element, 'superguy'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(element.data('classify')).toBe('add-superguy'); - }); - }); - - - it("should not skip ngAnimate animations when any pre-existing CSS transitions are present on the element", function() { - inject(function($compile, $rootScope, $animate, $timeout, $sniffer) { - if (!$sniffer.transitions) return; - - var element = html($compile('
')($rootScope)); - var child = html($compile('
')($rootScope)); - - ss.addRule('.animated', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); - ss.addRule('.super-add', '-webkit-transition:2s linear all;' + - 'transition:2s linear all;'); - - $rootElement.append(element); - jqLite(document.body).append($rootElement); - - $animate.addClass(element, 'super'); - - var empty = true; - try { - $animate.triggerReflow(); - empty = false; - } - catch (e) {} - - expect(empty).toBe(false); - }); - }); - - - it("should wait until both the duration and delay are complete to close off the animation", - inject(function($compile, $rootScope, $animate, $timeout, $sniffer) { - - if (!$sniffer.transitions) return; - - var element = html($compile('
')($rootScope)); - var child = html($compile('
')($rootScope)); - - ss.addRule('.animated.ng-enter', '-webkit-transition: width 1s, background 1s 1s;' + - 'transition: width 1s, background 1s 1s;'); - - $rootElement.append(element); - jqLite(document.body).append($rootElement); - - $animate.enter(child, element); - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(child.hasClass('ng-enter')).toBe(true); - expect(child.hasClass('ng-enter-active')).toBe(true); - - browserTrigger(child, 'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 0 }); - - expect(child.hasClass('ng-enter')).toBe(true); - expect(child.hasClass('ng-enter-active')).toBe(true); - - browserTrigger(child, 'transitionend', { timeStamp: Date.now() + 2000, elapsedTime: 2 }); - - expect(child.hasClass('ng-enter')).toBe(false); - expect(child.hasClass('ng-enter-active')).toBe(false); - - expect(element.contents().length).toBe(1); - })); - - - it("should cancel all child animations when a leave or move animation is triggered on a parent element", function() { - - var step, animationState; - module(function($animateProvider) { - $animateProvider.register('.animan', function() { - return { - enter: function(element, done) { - animationState = 'enter'; - step = done; - return function(cancelled) { - animationState = cancelled ? 'enter-cancel' : animationState; - }; - }, - addClass: function(element, className, done) { - animationState = 'addClass'; - step = done; - return function(cancelled) { - animationState = cancelled ? 'addClass-cancel' : animationState; - }; - } - }; - }); - }); - - inject(function($animate, $compile, $rootScope, $timeout, $sniffer) { - var element = html($compile('
')($rootScope)); - var container = html($compile('
')($rootScope)); - var child = html($compile('
')($rootScope)); - - ss.addRule('.animan.ng-enter, .animan.something-add', '-webkit-transition: width 1s, background 1s 1s;' + - 'transition: width 1s, background 1s 1s;'); - - $rootElement.append(element); - jqLite(document.body).append($rootElement); - - $animate.enter(child, element); - $rootScope.$digest(); - - expect(animationState).toBe('enter'); - if ($sniffer.transitions) { - expect(child.hasClass('ng-enter')).toBe(true); - $animate.triggerReflow(); - expect(child.hasClass('ng-enter-active')).toBe(true); - } - - $animate.move(element, container); - if ($sniffer.transitions) { - expect(child.hasClass('ng-enter')).toBe(false); - expect(child.hasClass('ng-enter-active')).toBe(false); - } - - expect(animationState).toBe('enter-cancel'); - - $rootScope.$digest(); - $animate.triggerCallbacks(); - - $animate.addClass(child, 'something'); - $rootScope.$digest(); - if ($sniffer.transitions) { - $animate.triggerReflow(); - } - expect(animationState).toBe('addClass'); - if ($sniffer.transitions) { - expect(child.hasClass('something-add')).toBe(true); - expect(child.hasClass('something-add-active')).toBe(true); - } - - $animate.leave(container); - expect(animationState).toBe('addClass-cancel'); - if ($sniffer.transitions) { - expect(child.hasClass('something-add')).toBe(false); - expect(child.hasClass('something-add-active')).toBe(false); - } - }); - - }); - - it('should coalesce all class-based animation calls together into a single animation', function() { - var log = []; - var track = function(name) { - return function() { - log.push({ name: name, className: arguments[1] }); - }; - }; - module(function($animateProvider) { - $animateProvider.register('.animate', function() { - return { - addClass: track('addClass'), - removeClass: track('removeClass') - }; - }); - }); - inject(function($rootScope, $animate, $compile, $rootElement, $document) { - $animate.enabled(true); - - var element = $compile('
')($rootScope); - $rootElement.append(element); - angular.element($document[0].body).append($rootElement); - - $animate.addClass(element, 'one'); - $animate.addClass(element, 'two'); - $animate.removeClass(element, 'three'); - $animate.removeClass(element, 'four'); - $animate.setClass(element, 'four five', 'two'); - - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(log.length).toBe(2); - expect(log[0]).toEqual({ name: 'addClass', className: 'one four five' }); - expect(log[1]).toEqual({ name: 'removeClass', className: 'three' }); - }); - }); - - it('should intelligently cancel out redundant class-based animations', function() { - var log = []; - var track = function(name) { - return function() { - log.push({ name: name, className: arguments[1] }); - }; - }; - module(function($animateProvider) { - $animateProvider.register('.animate', function() { - return { - addClass: track('addClass'), - removeClass: track('removeClass') - }; - }); - }); - inject(function($rootScope, $animate, $compile, $rootElement, $document) { - $animate.enabled(true); - - var element = $compile('
')($rootScope); - $rootElement.append(element); - angular.element($document[0].body).append($rootElement); - - $animate.removeClass(element, 'one'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(log.length).toBe(0); - $animate.triggerCallbacks(); - - $animate.addClass(element, 'two'); - $animate.addClass(element, 'two'); - $animate.removeClass(element, 'two'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(log.length).toBe(0); - $animate.triggerCallbacks(); - - $animate.removeClass(element, 'three'); - $animate.addClass(element, 'three'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(log.length).toBe(0); - $animate.triggerCallbacks(); - - $animate.removeClass(element, 'four'); - $animate.addClass(element, 'four'); - $animate.removeClass(element, 'four'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(log.length).toBe(1); - $animate.triggerCallbacks(); - expect(log[0]).toEqual({ name: 'removeClass', className: 'four' }); - - $animate.addClass(element, 'five'); - $animate.addClass(element, 'five'); - $animate.addClass(element, 'five'); - $animate.removeClass(element, 'five'); - $animate.addClass(element, 'five'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(log.length).toBe(2); - $animate.triggerCallbacks(); - expect(log[1]).toEqual({ name: 'addClass', className: 'five' }); - }); - }); - - it('should skip class-based animations if the element is removed before the digest occurs', function() { - var spy = jasmine.createSpy(); - module(function($animateProvider) { - $animateProvider.register('.animated', function() { - return { - beforeAddClass: spy, - beforeRemoveClass: spy, - beforeSetClass: spy - }; - }); - }); - inject(function($rootScope, $animate, $compile, $rootElement, $document) { - $animate.enabled(true); - - var one = $compile('
')($rootScope); - var two = $compile('
')($rootScope); - var three = $compile('
')($rootScope); - - $rootElement.append(one); - $rootElement.append(two); - angular.element($document[0].body).append($rootElement); - - $animate.addClass(one, 'active-class'); - one.remove(); - - $rootScope.$digest(); - expect(spy).not.toHaveBeenCalled(); - - $animate.addClass(two, 'active-class'); - - $rootScope.$digest(); - expect(spy).toHaveBeenCalled(); - - spy.reset(); - $animate.removeClass(two, 'active-class'); - two.remove(); - - $rootScope.$digest(); - expect(spy).not.toHaveBeenCalled(); - - $animate.setClass(three, 'active-class', 'three'); - three.remove(); - - $rootScope.$digest(); - expect(spy).not.toHaveBeenCalled(); - }); - }); - - it('should skip class-based animations if ngRepeat has marked the element or its parent for removal', function() { - var spy = jasmine.createSpy(); - module(function($animateProvider) { - $animateProvider.register('.animated', function() { - return { - beforeAddClass: spy, - beforeRemoveClass: spy, - beforeSetClass: spy - }; - }); - }); - inject(function($rootScope, $animate, $compile, $rootElement, $document) { - $animate.enabled(true); - - var element = $compile( - '
' + - '
' + - ' {{ $index }}' + - '
' + - '
' - )($rootScope); - - $rootElement.append(element); - angular.element($document[0].body).append($rootElement); - - $rootScope.items = [1,2,3]; - $rootScope.$digest(); - - var child = element.find('div'); - - $animate.addClass(child, 'start-animation'); - $rootScope.items = [2,3]; - $rootScope.$digest(); - - expect(spy).not.toHaveBeenCalled(); - - var innerChild = element.find('span'); - - $animate.addClass(innerChild, 'start-animation'); - $rootScope.items = [3]; - $rootScope.$digest(); - - expect(spy).not.toHaveBeenCalled(); - dealoc(element); - }); - }); - - it('should call class-based animation callbacks in the correct order when animations are skipped', function() { - var continueAnimation; - module(function($animateProvider) { - $animateProvider.register('.animate', function() { - return { - addClass: function(element, className, done) { - continueAnimation = done; - } - }; - }); - }); - inject(function($rootScope, $animate, $compile, $rootElement, $document) { - $animate.enabled(true); - - var element = $compile('
')($rootScope); - $rootElement.append(element); - angular.element($document[0].body).append($rootElement); - - var log = ''; - $animate.addClass(element, 'one').then(function() { - log += 'A'; - }); - $rootScope.$digest(); - - $animate.addClass(element, 'one').then(function() { - log += 'B'; - }); - $rootScope.$digest(); - $animate.triggerCallbackPromise(); - - $animate.triggerReflow(); - continueAnimation(); - $animate.triggerCallbackPromise(); - expect(log).toBe('BA'); - }); - }); - - it('should skip class-based animations when add class and remove class cancel each other out', function() { - var spy = jasmine.createSpy(); - module(function($animateProvider) { - $animateProvider.register('.animate', function() { - return { - addClass: spy, - removeClass: spy - }; - }); - }); - inject(function($rootScope, $animate, $compile) { - $animate.enabled(true); - - var element = $compile('
')($rootScope); - - var count = 0; - var callback = function() { - count++; - }; - - $animate.addClass(element, 'on').then(callback); - $animate.addClass(element, 'on').then(callback); - $animate.removeClass(element, 'on').then(callback); - $animate.removeClass(element, 'on').then(callback); - - $rootScope.$digest(); - $animate.triggerCallbackPromise(); - - expect(spy).not.toHaveBeenCalled(); - expect(count).toBe(4); - }); - }); - - it("should wait until a queue of animations are complete before performing a reflow", - inject(function($rootScope, $compile, $timeout, $sniffer, $animate) { - - if (!$sniffer.transitions) return; - - $rootScope.items = [1,2,3,4,5]; - var element = html($compile('
')($rootScope)); - - ss.addRule('.animated.ng-enter', '-webkit-transition: width 1s, background 1s 1s;' + - 'transition: width 1s, background 1s 1s;'); - - $rootScope.$digest(); - expect(element[0].querySelectorAll('.ng-enter-active').length).toBe(0); - $animate.triggerReflow(); - expect(element[0].querySelectorAll('.ng-enter-active').length).toBe(5); - - forEach(element.children(), function(kid) { - browserTrigger(kid, 'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - }); - - expect(element[0].querySelectorAll('.ng-enter-active').length).toBe(0); - })); - - - it("should work to disable all child animations for an element", function() { - var childAnimated = false, - containerAnimated = false; - module(function($animateProvider) { - $animateProvider.register('.child', function() { - return { - addClass: function(element, className, done) { - childAnimated = true; - done(); - } - }; - }); - $animateProvider.register('.container', function() { - return { - leave: function(element, done) { - containerAnimated = true; - done(); - } - }; - }); - }); - - inject(function($compile, $rootScope, $animate, $timeout, $rootElement) { - $animate.enabled(true); - - var element = $compile('
')($rootScope); - jqLite($document[0].body).append($rootElement); - $rootElement.append(element); - - var child = $compile('
')($rootScope); - element.append(child); - - $animate.enabled(true, element); - - $animate.addClass(child, 'awesome'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(childAnimated).toBe(true); - - childAnimated = false; - $animate.enabled(false, element); - - $animate.addClass(child, 'super'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(childAnimated).toBe(false); - - $animate.leave(element); - $rootScope.$digest(); - expect(containerAnimated).toBe(true); - }); - }); - - - it("should disable all child animations on structural animations until the post animation " + - "timeout has passed as well as all structural animations", function() { - var intercepted, continueAnimation; - module(function($animateProvider) { - $animateProvider.register('.animated', function() { - return { - enter: ani('enter'), - leave: ani('leave'), - move: ani('move'), - addClass: ani('addClass'), - removeClass: ani('removeClass') - }; - - function ani(type) { - return function(element, className, done) { - intercepted = type; - continueAnimation = function() { - continueAnimation = angular.noop; - (done || className)(); - }; - }; - } - }); - }); - - inject(function($animate, $rootScope, $sniffer, $timeout, $compile, _$rootElement_) { - $rootElement = _$rootElement_; - - $animate.enabled(true); - $rootScope.$digest(); - - var element = $compile('
...
')($rootScope); - var child1 = $compile('
...
')($rootScope); - var child2 = $compile('
...
')($rootScope); - var container = $compile('
...
')($rootScope); - - var body = angular.element($document[0].body); - body.append($rootElement); - $rootElement.append(container); - element.append(child1); - element.append(child2); - - $animate.enter(element, container); - $rootScope.$digest(); - - expect(intercepted).toBe('enter'); - continueAnimation(); - - $animate.addClass(child1, 'test'); - $rootScope.$digest(); - $animate.triggerReflow(); - expect(child1.hasClass('test')).toBe(true); - - expect(element.children().length).toBe(2); - - expect(intercepted).toBe('enter'); - $animate.leave(child1); - $rootScope.$digest(); - - expect(element.children().length).toBe(1); - - expect(intercepted).toBe('enter'); - - $animate.move(element, null, container); - $rootScope.$digest(); - - expect(intercepted).toBe('move'); - - //flush the POST enter callback - $animate.triggerCallbacks(); - - $animate.addClass(child2, 'testing'); - $rootScope.$digest(); - expect(intercepted).toBe('move'); - - continueAnimation(); - - //flush the POST move callback - $animate.triggerCallbacks(); - - $animate.leave(child2); - $rootScope.$digest(); - expect(intercepted).toBe('leave'); - }); - }); - - - it("should not disable any child animations when any parent class-based animations are run", function() { - var intercepted; - module(function($animateProvider) { - $animateProvider.register('.animated', function() { - return { - enter: function(element, done) { - intercepted = true; - done(); - } - }; - }); - }); - - inject(function($animate, $rootScope, $sniffer, $timeout, $compile, $document, $rootElement) { - $animate.enabled(true); - - var element = $compile('
value
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - $rootScope.bool = true; - $rootScope.$digest(); - - expect(intercepted).toBe(true); - }); - }); - - - it("should cache the response from getComputedStyle if each successive element has the same className value and parent until the first reflow hits", function() { - var count = 0; - module(function($provide) { - $provide.value('$window', { - document: jqLite(window.document), - getComputedStyle: function(element) { - count++; - return window.getComputedStyle(element); - } - }); - }); - - inject(function($animate, $rootScope, $compile, $rootElement, $timeout, $document, $sniffer) { - if (!$sniffer.transitions) return; - - $animate.enabled(true); - - var kid, element = $compile('
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - for (var i = 0; i < 20; i++) { - kid = $compile('
')($rootScope); - $animate.enter(kid, element); - } - $rootScope.$digest(); - - //called three times since the classname is the same - expect(count).toBe(2); - - dealoc(element); - count = 0; - - for (i = 0; i < 20; i++) { - kid = $compile('
')($rootScope); - $animate.enter(kid, element); - } - - $rootScope.$digest(); - - expect(count).toBe(20); - }); - }); - - it("should cache getComputedStyle with similar className values but with respect to the parent node", - inject(function($compile, $rootScope, $animate, $sniffer) { - - if (!$sniffer.transitions) return; - - $animate.enabled(); - - var html = '
first
' + - '
' + - '
second
' + - '
'; - - ss.addRule('.second .on', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); - - var element = $compile(html)($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - $rootScope.$apply(function() { - $rootScope.one = true; - $rootScope.two = true; - }); - - $animate.triggerReflow(); - - var inner = jqLite(jqLite(element[1]).find('div')); - - expect(inner.hasClass('on-add')).toBe(true); - expect(inner.hasClass('on-add-active')).toBe(true); - - browserTrigger(inner, 'animationend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - - expect(inner.hasClass('on-add')).toBe(false); - expect(inner.hasClass('on-add-active')).toBe(false); - })); - - it("should reset the getComputedStyle lookup cache even when no animation is found", - inject(function($compile, $rootScope, $animate, $sniffer, $document) { - - if (!$sniffer.transitions) return; - - $animate.enabled(); - - var html = '
' + - '
On or Off
' + - '
'; - - ss.addRule('.activated .toggle', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); - - var child, element = $compile(html)($rootScope); - - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - $rootScope.onOff = true; - $rootScope.$digest(); - - child = element.find('div'); - expect(child).not.toHaveClass('ng-enter'); - expect(child.parent()[0]).toEqual(element[0]); - $animate.triggerReflow(); - - $rootScope.onOff = false; - $rootScope.$digest(); - - child = element.find('div'); - expect(child.parent().length).toBe(0); - $animate.triggerReflow(); - - element.addClass('activated'); - $rootScope.$digest(); - $animate.triggerReflow(); - - $rootScope.onOff = true; - $rootScope.$digest(); - - child = element.find('div'); - expect(child).toHaveClass('ng-enter'); - $animate.triggerReflow(); - expect(child).toHaveClass('ng-enter-active'); - - browserTrigger(child, 'transitionend', - { timeStamp: Date.now() + 1000, elapsedTime: 2000 }); - - $animate.triggerCallbacks(); - - $rootScope.onOff = false; - $rootScope.$digest(); - - expect(child).toHaveClass('ng-leave'); - $animate.triggerReflow(); - expect(child).toHaveClass('ng-leave-active'); - })); - - it("should cancel and perform the dom operation only after the reflow has run", - inject(function($compile, $rootScope, $animate, $sniffer) { - - if (!$sniffer.transitions) return; - - ss.addRule('.green-add', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); - - ss.addRule('.red-add', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); - - var element = $compile('
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - $animate.addClass(element, 'green'); - $rootScope.$digest(); - expect(element.hasClass('green-add')).toBe(true); - - $animate.addClass(element, 'red'); - $rootScope.$digest(); - expect(element.hasClass('red-add')).toBe(true); - - expect(element.hasClass('green')).toBe(false); - expect(element.hasClass('red')).toBe(false); - - $animate.triggerReflow(); - - expect(element.hasClass('green')).toBe(true); - expect(element.hasClass('red')).toBe(true); - })); - - it("should properly add and remove CSS classes when multiple classes are applied", - inject(function($compile, $rootScope, $animate) { - - $animate.enabled(); - - var exp = "{{ className ? 'before ' + className + ' after' : '' }}"; - var element = $compile('
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - function assertClasses(str) { - var className = element.attr('class'); - if (str.length === 0) { - expect(className.length).toBe(0); - } else { - expect(className.split(/\s+/)).toEqual(str.split(' ')); - } - } - - $rootScope.className = ''; - $rootScope.$digest(); - $animate.triggerReflow(); - - assertClasses(''); - - $rootScope.className = 'one'; - $rootScope.$digest(); - $animate.triggerReflow(); - - assertClasses('before one after'); - - $rootScope.className = 'two'; - $rootScope.$digest(); - $animate.triggerReflow(); - - assertClasses('before after two'); - - $rootScope.className = ''; - $rootScope.$digest(); - //intentionally avoiding the triggerReflow operation - - assertClasses(''); - })); - - it("should avoid mixing up substring classes during add and remove operations", function() { - var currentAnimation, currentFn; - module(function($animateProvider) { - $animateProvider.register('.on', function() { - return { - beforeAddClass: function(element, className, done) { - currentAnimation = 'addClass'; - currentFn = done; - return function(cancelled) { - currentAnimation = cancelled ? null : currentAnimation; - }; - }, - beforeRemoveClass: function(element, className, done) { - currentAnimation = 'removeClass'; - currentFn = done; - return function(cancelled) { - currentAnimation = cancelled ? null : currentAnimation; - }; - } - }; - }); - }); - inject(function($compile, $rootScope, $animate) { - var element = $compile('
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - $animate.addClass(element, 'on'); - $rootScope.$digest(); - expect(currentAnimation).toBe('addClass'); - currentFn(); - - currentAnimation = null; - - $animate.removeClass(element, 'on'); - $rootScope.$digest(); - - $animate.addClass(element, 'on'); - $rootScope.$digest(); - - expect(currentAnimation).toBe('addClass'); - }); - }); - - it('should enable and disable animations properly on the root element', function() { - var count = 0; - module(function($animateProvider) { - $animateProvider.register('.animated', function() { - return { - addClass: function(element, className, done) { - count++; - done(); - } - }; - }); - }); - inject(function($compile, $rootScope, $animate, $sniffer, $rootElement) { - - $rootElement.addClass('animated'); - $animate.addClass($rootElement, 'green'); - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(count).toBe(1); - - $animate.addClass($rootElement, 'red'); - $rootScope.$digest(); - $animate.triggerReflow(); - - expect(count).toBe(2); - }); - }); - - - it('should perform pre and post animations', function() { - var steps = []; - module(function($animateProvider) { - $animateProvider.register('.class-animate', function() { - return { - beforeAddClass: function(element, className, done) { - steps.push('before'); - done(); - }, - addClass: function(element, className, done) { - steps.push('after'); - done(); - } - }; - }); - }); - inject(function($animate, $rootScope, $compile, $rootElement) { - $animate.enabled(true); - - var element = $compile('
')($rootScope); - $rootElement.append(element); - - $animate.addClass(element, 'red'); - $rootScope.$digest(); - - $animate.triggerReflow(); - - expect(steps).toEqual(['before','after']); - }); - }); - - - it('should treat the leave event always as a before event and discard the beforeLeave function', function() { - var parentID, steps = []; - module(function($animateProvider) { - $animateProvider.register('.animate', function() { - return { - beforeLeave: function(element, done) { - steps.push('before'); - done(); - }, - leave: function(element, done) { - parentID = element.parent().attr('id'); - steps.push('after'); - done(); - } - }; - }); - }); - inject(function($animate, $rootScope, $compile, $rootElement) { - $animate.enabled(true); - - var element = $compile('
')($rootScope); - var child = $compile('
')($rootScope); - $rootElement.append(element); - element.append(child); - - $animate.leave(child); - $rootScope.$digest(); - - expect(steps).toEqual(['after']); - expect(parentID).toEqual('parentGuy'); - }); - }); - - - it('should only perform the DOM operation once', - inject(function($sniffer, $compile, $rootScope, $rootElement, $animate) { - - if (!$sniffer.transitions) return; - - ss.addRule('.base-class', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); - - $animate.enabled(true); - - var element = $compile('
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - $animate.removeClass(element, 'base-class one two'); - $rootScope.$digest(); - - //still true since we're before the reflow - expect(element.hasClass('base-class')).toBe(true); - - //this will cancel the remove animation - $animate.addClass(element, 'base-class one two'); - $rootScope.$digest(); - - //the cancellation was a success and the class was removed right away - expect(element.hasClass('base-class')).toBe(false); - - //the reflow... - $animate.triggerReflow(); - - //the reflow DOM operation was commenced... - expect(element.hasClass('base-class')).toBe(true); - })); - - - it('should block and unblock transitions before the dom operation occurs', - inject(function($rootScope, $compile, $rootElement, $document, $animate, $sniffer) { - - if (!$sniffer.transitions) return; - - $animate.enabled(true); - - ss.addRule('.cross-animation', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); - - var capturedProperty = 'none'; - - var element = $compile('
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - var node = element[0]; - node._setAttribute = node.setAttribute; - node.setAttribute = function(prop, val) { - if (prop == 'class' && val.indexOf('trigger-class') >= 0) { - var propertyKey = ($sniffer.vendorPrefix == 'Webkit' ? '-webkit-' : '') + 'transition-property'; - capturedProperty = element.css(propertyKey); - } - node._setAttribute(prop, val); - }; - - expect(capturedProperty).toBe('none'); - $animate.addClass(element, 'trigger-class'); - $rootScope.$digest(); - - $animate.triggerReflow(); - - expect(capturedProperty).not.toBe('none'); - })); - - - it('should not block keyframe animations around the reflow operation', - inject(function($rootScope, $compile, $rootElement, $document, $animate, $sniffer) { - - if (!$sniffer.animations) return; - - $animate.enabled(true); - - ss.addRule('.cross-animation', '-webkit-animation:1s my_animation;' + - 'animation:1s my_animation;'); - - var element = $compile('
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - var node = element[0]; - var animationKey = $sniffer.vendorPrefix == 'Webkit' ? 'WebkitAnimation' : 'animation'; - - $animate.addClass(element, 'trigger-class'); - $rootScope.$digest(); - - expect(node.style[animationKey]).not.toContain('none'); - - $animate.triggerReflow(); - - expect(node.style[animationKey]).not.toContain('none'); - - browserTrigger(element, 'animationend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - - expect(node.style[animationKey]).not.toContain('none'); - })); - - - it('should not block keyframe animations at anytime before a followup JS animation occurs', function() { - module(function($animateProvider) { - $animateProvider.register('.special', function($sniffer, $window) { - var prop = $sniffer.vendorPrefix == 'Webkit' ? 'WebkitAnimation' : 'animation'; - return { - beforeAddClass: function(element, className, done) { - expect(element[0].style[prop]).not.toContain('none'); - expect($window.getComputedStyle(element[0])[prop + 'Duration']).toBe('1s'); - done(); - }, - addClass: function(element, className, done) { - expect(element[0].style[prop]).not.toContain('none'); - expect($window.getComputedStyle(element[0])[prop + 'Duration']).toBe('1s'); - done(); - } - }; - }); - }); - inject(function($rootScope, $compile, $rootElement, $document, $animate, $sniffer, $timeout, $window) { - if (!$sniffer.animations) return; - - $animate.enabled(true); - - ss.addRule('.special', '-webkit-animation:1s special_animation;' + - 'animation:1s special_animation;'); - - var element = $compile('
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - $animate.addClass(element, 'some-klass'); + var runner2 = $animate.leave(element); $rootScope.$digest(); - var prop = $sniffer.vendorPrefix == 'Webkit' ? 'WebkitAnimation' : 'animation'; - - expect(element[0].style[prop]).not.toContain('none'); - expect($window.getComputedStyle(element[0])[prop + 'Duration']).toBe('1s'); - - $animate.triggerReflow(); - }); + expect(runner1).not.toBe(runner2); + })); }); + describe('should merge', function() { + it('multiple class-based animations together into one before the digest passes', inject(function($animate, $rootScope) { + parent.append(element); + element.addClass('green'); - it('should round up long elapsedTime values to close off a CSS3 animation', - inject(function($rootScope, $compile, $rootElement, $document, $animate, $sniffer) { - if (!$sniffer.animations) return; - - ss.addRule('.millisecond-transition.ng-leave', '-webkit-transition:510ms linear all;' + - 'transition:510ms linear all;'); - - var element = $compile('
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); + $animate.addClass(element, 'red'); + $animate.addClass(element, 'blue'); + $animate.removeClass(element, 'green'); - $animate.leave(element); $rootScope.$digest(); - $animate.triggerReflow(); + expect(capturedAnimation[0]).toBe(element); + expect(capturedAnimation[1]).toBe('setClass'); - browserTrigger(element, 'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 0.50999999991 }); + options = capturedAnimation[2]; + expect(options.addClass).toEqual('red blue'); + expect(options.removeClass).toEqual('green'); - expect($rootElement.children().length).toBe(0); - }) - ); + expect(element).not.toHaveClass('red'); + expect(element).not.toHaveClass('blue'); + expect(element).toHaveClass('green'); + applyAnimationClasses(element, capturedAnimation[2]); - it('should properly animate elements with compound directives', function() { - var capturedAnimation; - module(function($animateProvider) { - $animateProvider.register('.special', function() { - return { - enter: function(element, done) { - capturedAnimation = 'enter'; - done(); - }, - leave: function(element, done) { - capturedAnimation = 'leave'; - done(); - } - }; - }); - }); - inject(function($rootScope, $compile, $rootElement, $document, $timeout, $templateCache, $sniffer, $animate) { - if (!$sniffer.transitions) return; + expect(element).toHaveClass('red'); + expect(element).toHaveClass('blue'); + expect(element).not.toHaveClass('green'); + })); - $templateCache.put('item-template', 'item: #{{ item }} '); - var element = $compile('
' + - '
' + - '
')($rootScope); + it('multiple class-based animations together into a single structural event before the digest passes', inject(function($animate, $rootScope) { + element.addClass('green'); - ss.addRule('.special', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); + expect(element.parent().length).toBe(0); + $animate.enter(element, parent); + expect(element.parent().length).toBe(1); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); + $animate.addClass(element, 'red'); + $animate.removeClass(element, 'green'); - $rootScope.tpl = 'item-template'; - $rootScope.items = [1,2,3]; $rootScope.$digest(); - $animate.triggerReflow(); - expect(capturedAnimation).toBe('enter'); - expect(element.text()).toContain('item: #1'); + expect(capturedAnimation[0]).toBe(element); + expect(capturedAnimation[1]).toBe('enter'); - forEach(element.children(), function(kid) { - browserTrigger(kid, 'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); - }); - $animate.triggerCallbackPromise(); + options = capturedAnimation[2]; + expect(options.addClass).toEqual('red'); + expect(options.removeClass).toEqual('green'); - $rootScope.items = []; - $rootScope.$digest(); - $animate.triggerReflow(); + expect(element).not.toHaveClass('red'); + expect(element).toHaveClass('green'); - expect(capturedAnimation).toBe('leave'); - }); - }); + applyAnimationClasses(element, capturedAnimation[2]); - it('should animate only the specified CSS className', function() { - var captures = {}; - module(function($animateProvider) { - $animateProvider.classNameFilter(/prefixed-animation/); - $animateProvider.register('.capture', function() { - return { - enter: buildFn('enter'), - leave: buildFn('leave') - }; - - function buildFn(key) { - return function(element, className, done) { - captures[key] = true; - (done || className)(); - }; - } - }); - }); - inject(function($rootScope, $compile, $rootElement, $document, $timeout, $templateCache, $sniffer, $animate) { - if (!$sniffer.transitions) return; + expect(element).toHaveClass('red'); + expect(element).not.toHaveClass('green'); + })); - var element = $compile('
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); + it('should automatically cancel out class-based animations if the element already contains or doesn\' contain the applied classes', + inject(function($animate, $rootScope) { - var enterDone = false; - $animate.enter(element, $rootElement).then(function() { - enterDone = true; - }); + parent.append(element); + element.addClass('one three'); + + $animate.addClass(element, 'one'); + $animate.addClass(element, 'two'); + $animate.removeClass(element, 'three'); + $animate.removeClass(element, 'four'); $rootScope.$digest(); - $animate.triggerCallbackPromise(); - expect(captures['enter']).toBeUndefined(); - expect(enterDone).toBe(true); + options = capturedAnimation[2]; + expect(options.addClass).toEqual('two'); + expect(options.removeClass).toEqual('three'); + })); - element.addClass('prefixed-animation'); + it('and skip the animation entirely if no class-based animations remain and if there is no structural animation applied', + inject(function($animate, $rootScope) { - var leaveDone = false; - $animate.leave(element).then(function() { - leaveDone = true; - }); + parent.append(element); + element.addClass('one three'); + + $animate.addClass(element, 'one'); + $animate.removeClass(element, 'four'); $rootScope.$digest(); - $animate.triggerCallbackPromise(); + expect(capturedAnimation).toBeFalsy(); + })); - expect(captures['leave']).toBe(true); - expect(leaveDone).toBe(true); - }); - }); + it('but not skip the animation if it is a structural animation and if there are no classes to be animated', + inject(function($animate, $rootScope) { - it('should animate only the specified CSS className inside ng-if', function() { - var captures = {}; - module(function($animateProvider) { - $animateProvider.classNameFilter(/prefixed-animation/); - $animateProvider.register('.capture', function() { - return { - enter: buildFn('enter'), - leave: buildFn('leave') - }; - - function buildFn(key) { - return function(element, className, done) { - captures[key] = true; - (done || className)(); - }; - } - }); - }); - inject(function($rootScope, $compile, $rootElement, $document, $sniffer, $animate) { - if (!$sniffer.transitions) return; + element.addClass('one three'); - var upperElement = $compile('
')($rootScope); - $rootElement.append(upperElement); - jqLite($document[0].body).append($rootElement); + $animate.addClass(element, 'one'); + $animate.removeClass(element, 'four'); + $animate.enter(element, parent); $rootScope.$digest(); - $animate.triggerCallbacks(); - - var element = upperElement.find('span'); - var leaveDone = false; - $animate.leave(element).then(function() { - leaveDone = true; - }); + expect(capturedAnimation[1]).toBe('enter'); + })); - $rootScope.$digest(); - $animate.triggerCallbacks(); + it('class-based animations, however it should also cancel former structural animations in the process', + inject(function($animate, $rootScope) { - expect(captures.leave).toBe(true); - expect(leaveDone).toBe(true); - }); - }); + element.addClass('green'); - it('should respect the most relevant CSS transition property if defined in multiple classes', - inject(function($sniffer, $compile, $rootScope, $rootElement, $animate) { + $animate.enter(element, parent); + $animate.addClass(element, 'red'); + $animate.removeClass(element, 'green'); + $animate.leave(element); - if (!$sniffer.transitions) return; + $rootScope.$digest(); - ss.addRule('.base-class', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); + expect(capturedAnimation[0]).toBe(element); + expect(capturedAnimation[1]).toBe('leave'); - ss.addRule('.base-class.on', '-webkit-transition:5s linear all;' + - 'transition:5s linear all;'); + // $$hashKey causes comparison issues + expect(element.parent()[0]).toEqual(parent[0]); - $animate.enabled(true); + options = capturedAnimation[2]; + expect(options.addClass).toEqual('red'); + expect(options.removeClass).toEqual('green'); + })); - var element = $compile('
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); + it('should retain the instance to the very first runner object when multiple element-level animations are issued', + inject(function($animate, $rootScope) { - var ready = false; - $animate.addClass(element, 'on').then(function() { - ready = true; - }); - $rootScope.$digest(); + element.addClass('green'); - $animate.triggerReflow(); - browserTrigger(element, 'transitionend', { timeStamp: Date.now(), elapsedTime: 1 }); - expect(ready).toBe(false); + var r1 = $animate.enter(element, parent); + var r2 = $animate.addClass(element, 'red'); + var r3 = $animate.removeClass(element, 'green'); - browserTrigger(element, 'transitionend', { timeStamp: Date.now(), elapsedTime: 5 }); - $animate.triggerReflow(); - $animate.triggerCallbackPromise(); - expect(ready).toBe(true); + expect(r1).toBe(r2); + expect(r2).toBe(r3); + })); + }); + }); - ready = false; - $animate.removeClass(element, 'on').then(function() { - ready = true; + describe('[ng-animate-children]', function() { + var parent, element, child, capturedAnimation, captureLog; + beforeEach(module(function($provide) { + capturedAnimation = null; + captureLog = []; + $provide.factory('$$animation', function($$AnimateRunner) { + return function(element, method, options) { + options.domOperation(); + captureLog.push(capturedAnimation = arguments); + return new $$AnimateRunner(); + }; }); - $rootScope.$digest(); - - $animate.triggerReflow(); - browserTrigger(element, 'transitionend', { timeStamp: Date.now(), elapsedTime: 1 }); - $animate.triggerCallbackPromise(); - expect(ready).toBe(true); + return function($rootElement, $document, $animate) { + jqLite($document[0].body).append($rootElement); + parent = jqLite('
'); + element = jqLite('
'); + child = jqLite('
'); + $animate.enabled(true); + }; })); - it('should not apply a transition upon removal of a class that has a transition', - inject(function($sniffer, $compile, $rootScope, $rootElement, $animate) { + it('should allow child animations to run when the attribute is used', + inject(function($animate, $rootScope, $rootElement, $compile) { - if (!$sniffer.transitions) return; - - ss.addRule('.base-class.on', '-webkit-transition:5s linear all;' + - 'transition:5s linear all;'); + $animate.enter(parent, $rootElement); + $animate.enter(element, parent); + $animate.enter(child, element); + $rootScope.$digest(); + expect(captureLog.length).toBe(1); - $animate.enabled(true); + captureLog = []; - var element = $compile('
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); + parent.attr('ng-animate-children', ''); + $compile(parent)($rootScope); + $rootScope.$digest(); - var ready = false; - $animate.removeClass(element, 'on').then(function() { - ready = true; - }); + $animate.enter(parent, $rootElement); $rootScope.$digest(); + expect(captureLog.length).toBe(1); - $animate.triggerReflow(); - $animate.triggerCallbackPromise(); - expect(ready).toBe(true); + $animate.enter(element, parent); + $animate.enter(child, element); + $rootScope.$digest(); + expect(captureLog.length).toBe(3); })); - it('should immediately close the former animation if the same CSS class is added/removed', - inject(function($sniffer, $compile, $rootScope, $rootElement, $animate) { - - if (!$sniffer.transitions) return; + it('should fully disallow all parallel child animations from running if `off` is used', + inject(function($animate, $rootScope, $rootElement, $compile) { - ss.addRule('.water-class', '-webkit-transition:2s linear all;' + - 'transition:2s linear all;'); + $rootElement.append(parent); + parent.append(element); + element.append(child); - $animate.enabled(true); + parent.attr('ng-animate-children', 'off'); + element.attr('ng-animate-children', 'on'); - var element = $compile('
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - var signature = ''; - $animate.removeClass(element, 'on').then(function() { - signature += 'A'; - }); + $compile(parent)($rootScope); + $compile(element)($rootScope); $rootScope.$digest(); - $animate.addClass(element, 'on').then(function() { - signature += 'B'; - }); + $animate.leave(parent); + $animate.leave(element); + $animate.leave(child); $rootScope.$digest(); - $animate.triggerReflow(); - $animate.triggerCallbackPromise(); - expect(signature).toBe('A'); + expect(captureLog.length).toBe(1); - browserTrigger(element, 'transitionend', { timeStamp: Date.now(), elapsedTime: 2000 }); - $animate.triggerCallbackPromise(); - - expect(signature).toBe('AB'); + dealoc(element); + dealoc(child); })); - it('should cancel the previous reflow when new animations are added', function() { - var cancelReflowCallback = jasmine.createSpy('callback'); - module(function($provide) { - $provide.value('$$animateReflow', function() { - return cancelReflowCallback; - }); - }); - inject(function($animate, $sniffer, $rootScope, $compile) { - if (!$sniffer.transitions) return; + it('should watch to see if the ng-animate-children attribute changes', + inject(function($animate, $rootScope, $rootElement, $compile) { - ss.addRule('.fly', '-webkit-transition:2s linear all;' + - 'transition:2s linear all;'); + $rootElement.append(parent); + $rootScope.val = 'on'; + parent.attr('ng-animate-children', '{{ val }}'); + $compile(parent)($rootScope); + $rootScope.$digest(); - $animate.enabled(true); + $animate.enter(parent, $rootElement); + $animate.enter(element, parent); + $animate.enter(child, element); + $rootScope.$digest(); + expect(captureLog.length).toBe(3); - var element = $compile('
')($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); + captureLog = []; - expect(cancelReflowCallback).not.toHaveBeenCalled(); + $rootScope.val = 'off'; + $rootScope.$digest(); - $animate.addClass(element, 'fast'); - $rootScope.$digest(); + $animate.leave(parent); + $animate.leave(element); + $animate.leave(child); + $rootScope.$digest(); - $animate.addClass(element, 'smooth'); - $rootScope.$digest(); - $animate.triggerReflow(); + expect(captureLog.length).toBe(1); - expect(cancelReflowCallback).toHaveBeenCalled(); - }); - }); + dealoc(element); + dealoc(child); + })); + }); - it('should immediately close off a leave animation if the element is removed from the DOM', function() { - var stat; - module(function($animateProvider) { - $animateProvider.register('.going', function() { - return { - leave: function() { - //left blank so it hangs - stat = 'leaving'; - return function(cancelled) { - stat = cancelled && 'gone'; - }; - } - }; - }); + describe('callbacks', function() { + var captureLog = []; + var capturedAnimation = []; + var runner; + var body; + beforeEach(module(function($provide) { + runner = null; + capturedAnimation = null; + $provide.factory('$$animation', function($$AnimateRunner) { + return function() { + captureLog.push(capturedAnimation = arguments); + return runner = new $$AnimateRunner(); + }; }); - inject(function($sniffer, $compile, $rootScope, $rootElement, $animate) { + return function($document, $rootElement, $animate) { + body = jqLite($document[0].body); + body.append($rootElement); $animate.enabled(true); + }; + })); - var element = $compile('
')($rootScope); - var child = $compile('
')($rootScope); - $rootElement.append(element); - element.append(child); - - $animate.leave(child); - $rootScope.$digest(); - - expect(stat).toBe('leaving'); - - child.remove(); + it('should trigger a callback for an enter animation', + inject(function($animate, $rootScope, $$rAF, $rootElement) { - expect(stat).toBe('gone'); + var callbackTriggered = false; + $animate.on('enter', body, function() { + callbackTriggered = true; }); - }); - - it('should remove all element and comment nodes during leave animation', - inject(function($compile, $rootScope) { - - $rootScope.items = [1,2,3,4,5]; - - var element = html($compile( - '
' + - '
start
' + - '
end
' + - '
' - )($rootScope)); + element = jqLite('
'); + $animate.enter(element, $rootElement); $rootScope.$digest(); - $rootScope.items = []; - - $rootScope.$digest(); + $$rAF.flush(); - expect(element.children().length).toBe(0); + expect(callbackTriggered).toBe(true); })); - it('should not throw an error when only comment nodes are rendered in the animation', - inject(function($rootScope, $compile) { - - $rootScope.items = [1,2,3,4,5]; - - var element = html($compile('
')($rootScope)); + it('should fire the callback with the signature of (element, phase, data)', + inject(function($animate, $rootScope, $$rAF, $rootElement) { - $rootScope.$digest(); + var capturedElement; + var capturedPhase; + var capturedData; + $animate.on('enter', body, + function(element, phase, data) { - $rootScope.items = []; + capturedElement = element; + capturedPhase = phase; + capturedData = data; + }); + element = jqLite('
'); + $animate.enter(element, $rootElement); $rootScope.$digest(); + $$rAF.flush(); - expect(element.children().length).toBe(0); + expect(capturedElement).toBe(element); + expect(isString(capturedPhase)).toBe(true); + expect(isObject(capturedData)).toBe(true); })); - describe('ngAnimateChildren', function() { - var spy; - - beforeEach(module(function($animateProvider) { - spy = jasmine.createSpy(); - $animateProvider.register('.parent', mockAnimate); - $animateProvider.register('.child', mockAnimate); - return function($animate) { - $animate.enabled(true); - }; - - function mockAnimate() { - return { - enter: spy, - leave: spy, - addClass: spy, - removeClass: spy - }; - } - })); - - it('should animate based on a boolean flag', inject(function($animate, $sniffer, $rootScope, $compile) { - var html = '
' + - '
...
' + - '
'; - - var element = $compile(html)($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - var scope = $rootScope; - - scope.bool = true; - scope.$digest(); - - scope.on1 = true; - scope.on2 = true; - scope.$digest(); - - $animate.triggerReflow(); - - expect(spy).toHaveBeenCalled(); - expect(spy.callCount).toBe(2); - - scope.bool = false; - scope.$digest(); - - scope.on1 = false; - scope.$digest(); - - scope.on2 = false; - scope.$digest(); - - $animate.triggerReflow(); - - expect(spy.callCount).toBe(3); - })); - - it('should default to true when no expression is provided', - inject(function($animate, $sniffer, $rootScope, $compile) { - - var html = '
' + - '
...
' + - '
'; - - var element = $compile(html)($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); - - $rootScope.on1 = true; - $rootScope.$digest(); - - $rootScope.on2 = true; - $rootScope.$digest(); - - $animate.triggerReflow(); + it('should not fire a callback if the element is outside of the given container', + inject(function($animate, $rootScope, $$rAF, $rootElement) { - expect(spy).toHaveBeenCalled(); - expect(spy.callCount).toBe(2); - })); + var callbackTriggered = false; + var innerContainer = jqLite('
'); + $rootElement.append(innerContainer); - it('should not perform inherited animations if any parent restricts it', - inject(function($animate, $sniffer, $rootScope, $compile) { + $animate.on('enter', innerContainer, + function(element, phase, data) { - var html = '
' + - ' ' + - '
'; + callbackTriggered = true; + }); - var element = $compile(html)($rootScope); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); + element = jqLite('
'); + $animate.enter(element, $rootElement); + $rootScope.$digest(); + $$rAF.flush(); - $rootScope.$digest(); + expect(callbackTriggered).toBe(false); + })); - $rootScope.on = true; - $rootScope.$digest(); + it('should fire a callback if the element is the given container', + inject(function($animate, $rootScope, $$rAF, $rootElement) { - $animate.triggerReflow(); + element = jqLite('
'); - expect(spy).toHaveBeenCalled(); - expect(spy.callCount).toBe(1); - })); + var callbackTriggered = false; + $animate.on('enter', element, + function(element, phase, data) { - it('should permit class-based animations when ng-animate-children is true for a structural animation', function() { - var spy = jasmine.createSpy(); - - module(function($animateProvider) { - $animateProvider.register('.inner', function() { - return { - beforeAddClass: function(element, className, done) { - spy(); - done(); - }, - beforeRemoveClass: function(element, className, done) { - spy(); - done(); - } - }; - }); - }); - - inject(function($animate, $sniffer, $rootScope, $compile) { - - $animate.enabled(true); - - var html = '
' + - '
...
' + - '
'; - - var element = angular.element(html); - $compile(element)($rootScope); - var body = angular.element($document[0].body); - body.append($rootElement); - - $rootScope.$watch('bool', function(bool) { - if (bool) { - $animate.enter(element, $rootElement); - } else if (element.parent().length) { - $animate.leave(element); - } - }); + callbackTriggered = true; + }); - $rootScope.$digest(); - expect(spy.callCount).toBe(0); + $animate.enter(element, $rootElement); + $rootScope.$digest(); + $$rAF.flush(); - $rootScope.bool = true; - $rootScope.$digest(); - $animate.triggerReflow(); - $animate.triggerCallbacks(); - expect(spy.callCount).toBe(1); + expect(callbackTriggered).toBe(true); + })); - $rootScope.bool = false; - $rootScope.$digest(); - $animate.triggerReflow(); - $animate.triggerCallbacks(); - expect(spy.callCount).toBe(2); - }); - }); - }); + it('should remove all the event-based event listeners when $animate.off(event) is called', + inject(function($animate, $rootScope, $$rAF, $rootElement) { - describe('SVG', function() { - it('should properly apply transitions on an SVG element', - inject(function($animate, $rootScope, $compile, $rootElement, $sniffer) { + element = jqLite('
'); - //jQuery doesn't handle SVG elements natively. Instead, an add-on library - //is required which is called jquery.svg.js. Therefore, when jQuery is - //active here there is no point to test this since it won't work by default. - if (!$sniffer.transitions) return; + var count = 0; + $animate.on('enter', element, counter); + $animate.on('enter', body, counter); - ss.addRule('circle.ng-enter', '-webkit-transition:1s linear all;' + - 'transition:1s linear all;'); + function counter(element, phase) { + count++; + } - var element = $compile('' + - '' + - '')($rootScope); + $animate.enter(element, $rootElement); + $rootScope.$digest(); + $$rAF.flush(); - $rootElement.append(element); - jqLite($document[0].body).append($rootElement); + expect(count).toBe(2); - $rootScope.$digest(); + $animate.off('enter'); - $rootScope.on = true; - $rootScope.$digest(); - $animate.triggerReflow(); + $animate.enter(element, $rootElement); + $rootScope.$digest(); + $$rAF.flush(); - var child = element.find('circle'); + expect(count).toBe(2); + })); - expect(jqLiteHasClass(child[0], 'ng-enter')).toBe(true); - expect(jqLiteHasClass(child[0], 'ng-enter-active')).toBe(true); + it('should remove the container-based event listeners when $animate.off(event, container) is called', + inject(function($animate, $rootScope, $$rAF, $rootElement) { - browserTrigger(child, 'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); + element = jqLite('
'); - expect(jqLiteHasClass(child[0], 'ng-enter')).toBe(false); - expect(jqLiteHasClass(child[0], 'ng-enter-active')).toBe(false); - })); + var count = 0; + $animate.on('enter', element, counter); + $animate.on('enter', body, counter); + function counter(element, phase) { + if (phase === 'start') { + count++; + } + } - it('should properly remove classes from SVG elements', inject(function($animate, $rootScope) { - var element = jqLite(''); - var child = element.find('rect'); - $animate.removeClass(child, 'class-of-doom'); + $animate.enter(element, $rootElement); + $rootScope.$digest(); + $$rAF.flush(); - $rootScope.$digest(); - expect(child.attr('class')).toBe(''); + expect(count).toBe(2); - dealoc(element); - })); - }); - }); + $animate.off('enter', body); + $animate.enter(element, $rootElement); + $rootScope.$digest(); + $$rAF.flush(); - describe('CSS class DOM manipulation', function() { - var element; - var addClass; - var removeClass; + expect(count).toBe(3); + })); - beforeEach(module(provideLog)); + it('should remove the callback-based event listener when $animate.off(event, container, callback) is called', + inject(function($animate, $rootScope, $$rAF, $rootElement) { - afterEach(function() { - dealoc(element); - }); + element = jqLite('
'); - function setupClassManipulationSpies() { - inject(function($animate) { - addClass = spyOn($originalAnimate, '$$addClassImmediately').andCallThrough(); - removeClass = spyOn($originalAnimate, '$$removeClassImmediately').andCallThrough(); - }); - } - - function setupClassManipulationLogger(log) { - inject(function($animate) { - var addClassImmediately = $originalAnimate.$$addClassImmediately; - var removeClassImmediately = $originalAnimate.$$removeClassImmediately; - addClass = spyOn($originalAnimate, '$$addClassImmediately').andCallFake(function(element, classes) { - var names = classes; - if (Object.prototype.toString.call(classes) === '[object Array]') names = classes.join(' '); - log('addClass(' + names + ')'); - return addClassImmediately.call($originalAnimate, element, classes); - }); - removeClass = spyOn($originalAnimate, '$$removeClassImmediately').andCallFake(function(element, classes) { - var names = classes; - if (Object.prototype.toString.call(classes) === '[object Array]') names = classes.join(' '); - log('removeClass(' + names + ')'); - return removeClassImmediately.call($originalAnimate, element, classes); - }); - }); - } + var count = 0; + $animate.on('enter', element, counter1); + $animate.on('enter', element, counter2); + function counter1(element, phase) { + if (phase === 'start') { + count++; + } + } - it('should defer class manipulation until end of digest', inject(function($rootScope, $animate, log) { - setupClassManipulationLogger(log); - element = jqLite('

test

'); + function counter2(element, phase) { + if (phase === 'start') { + count++; + } + } - $rootScope.$apply(function() { - $animate.addClass(element, 'test-class1'); - expect(element).not.toHaveClass('test-class1'); + $animate.enter(element, $rootElement); + $rootScope.$digest(); + $$rAF.flush(); - $animate.removeClass(element, 'test-class1'); + expect(count).toBe(2); - $animate.addClass(element, 'test-class2'); - expect(element).not.toHaveClass('test-class2'); + $animate.off('enter', element, counter2); - $animate.setClass(element, 'test-class3', 'test-class4'); - expect(element).not.toHaveClass('test-class3'); - expect(element).not.toHaveClass('test-class4'); - expect(log).toEqual([]); - }); + $animate.enter(element, $rootElement); + $rootScope.$digest(); + $$rAF.flush(); - expect(element).not.toHaveClass('test-class1'); - expect(element).not.toHaveClass('test-class4'); - expect(element).toHaveClass('test-class2'); - expect(element).toHaveClass('test-class3'); - expect(log).toEqual(['addClass(test-class2 test-class3)']); - expect(addClass.callCount).toBe(1); - expect(removeClass.callCount).toBe(0); + expect(count).toBe(3); })); + it('should fire a `start` callback when the animation starts with the matching element', + inject(function($animate, $rootScope, $$rAF, $rootElement) { - it('should defer class manipulation until postDigest when outside of digest', inject(function($rootScope, $animate, log) { - setupClassManipulationLogger(log); - element = jqLite('

test

'); + element = jqLite('
'); - $animate.addClass(element, 'test-class1'); - $animate.removeClass(element, 'test-class1'); - $animate.addClass(element, 'test-class2'); - $animate.setClass(element, 'test-class3', 'test-class4'); + var capturedState; + var capturedElement; + $animate.on('enter', body, function(element, phase) { + capturedState = phase; + capturedElement = element; + }); - expect(log).toEqual([]); + $animate.enter(element, $rootElement); $rootScope.$digest(); + $$rAF.flush(); - expect(log).toEqual(['addClass(test-class2 test-class3)', 'removeClass(test-class4)']); - expect(element).not.toHaveClass('test-class1'); - expect(element).toHaveClass('test-class2'); - expect(element).toHaveClass('test-class3'); - expect(addClass.callCount).toBe(1); - expect(removeClass.callCount).toBe(1); + expect(capturedState).toBe('start'); + expect(capturedElement).toBe(element); })); + it('should fire a `close` callback when the animation ends with the matching element', + inject(function($animate, $rootScope, $$rAF, $rootElement) { - it('should perform class manipulation in expected order at end of digest', inject(function($rootScope, $animate, log) { - element = jqLite('

test

'); + element = jqLite('
'); - setupClassManipulationLogger(log); - - $rootScope.$apply(function() { - $animate.addClass(element, 'test-class1'); - $animate.addClass(element, 'test-class2'); - $animate.removeClass(element, 'test-class1'); - $animate.removeClass(element, 'test-class3'); - $animate.addClass(element, 'test-class3'); + var capturedState; + var capturedElement; + $animate.on('enter', body, function(element, phase) { + capturedState = phase; + capturedElement = element; }); - expect(log).toEqual(['addClass(test-class2)']); - })); - - - it('should return a promise which is resolved on a different turn', inject(function(log, $animate, $browser, $rootScope) { - element = jqLite('

test

'); - - $animate.addClass(element, 'test1').then(log.fn('addClass(test1)')); - $animate.removeClass(element, 'test2').then(log.fn('removeClass(test2)')); + var runner = $animate.enter(element, $rootElement); $rootScope.$digest(); - expect(log).toEqual([]); - $browser.defer.flush(); - expect(log).toEqual(['addClass(test1)', 'removeClass(test2)']); - - log.reset(); - element = jqLite('

test

'); + runner.end(); + $$rAF.flush(); - $rootScope.$apply(function() { - $animate.addClass(element, 'test3').then(log.fn('addClass(test3)')); - $animate.removeClass(element, 'test4').then(log.fn('removeClass(test4)')); - expect(log).toEqual([]); - }); - - $browser.defer.flush(); - expect(log).toEqual(['addClass(test3)', 'removeClass(test4)']); + expect(capturedState).toBe('close'); + expect(capturedElement).toBe(element); })); + it('should remove the event listener if the element is removed', + inject(function($animate, $rootScope, $$rAF, $rootElement) { - it('should defer class manipulation until end of digest for SVG', inject(function($rootScope, $animate) { - if (!window.SVGElement) return; - setupClassManipulationSpies(); - element = jqLite(''); - var target = element.children().eq(0); - - $rootScope.$apply(function() { - $animate.addClass(target, 'test-class1'); - expect(target).not.toHaveClass('test-class1'); - - $animate.removeClass(target, 'test-class1'); + element = jqLite('
'); - $animate.addClass(target, 'test-class2'); - expect(target).not.toHaveClass('test-class2'); - - $animate.setClass(target, 'test-class3', 'test-class4'); - expect(target).not.toHaveClass('test-class3'); - expect(target).not.toHaveClass('test-class4'); - }); - - expect(target).not.toHaveClass('test-class1'); - expect(target).toHaveClass('test-class2'); - expect(addClass.callCount).toBe(1); - expect(removeClass.callCount).toBe(0); - })); + var count = 0; + $animate.on('enter', element, counter); + $animate.on('addClass', element, counter); + function counter(element, phase) { + if (phase === 'start') { + count++; + } + } - it('should defer class manipulation until postDigest when outside of digest for SVG', inject(function($rootScope, $animate, log) { - if (!window.SVGElement) return; - setupClassManipulationLogger(log); - element = jqLite(''); - var target = element.children().eq(0); + $animate.enter(element, $rootElement); + $rootScope.$digest(); + $$rAF.flush(); - $animate.addClass(target, 'test-class1'); - $animate.removeClass(target, 'test-class1'); - $animate.addClass(target, 'test-class2'); - $animate.setClass(target, 'test-class3', 'test-class4'); + expect(count).toBe(1); + element.remove(); - expect(log).toEqual([]); + $animate.addClass(element, 'viljami'); $rootScope.$digest(); - - expect(log).toEqual(['addClass(test-class2 test-class3)', 'removeClass(test-class4)']); - expect(target).not.toHaveClass('test-class1'); - expect(target).toHaveClass('test-class2'); - expect(target).toHaveClass('test-class3'); - expect(addClass.callCount).toBe(1); - expect(removeClass.callCount).toBe(1); + $$rAF.flush(); + expect(count).toBe(1); })); - - it('should perform class manipulation in expected order at end of digest for SVG', inject(function($rootScope, $animate, log) { - if (!window.SVGElement) return; - element = jqLite(''); - var target = element.children().eq(0); - - setupClassManipulationLogger(log); - - $rootScope.$apply(function() { - $animate.addClass(target, 'test-class1'); - $animate.addClass(target, 'test-class2'); - $animate.removeClass(target, 'test-class1'); - $animate.removeClass(target, 'test-class3'); - $animate.addClass(target, 'test-class3'); - }); - expect(log).toEqual(['addClass(test-class2)']); - })); }); }); diff --git a/test/ngAnimate/animationHelperFunctionsSpec.js b/test/ngAnimate/animationHelperFunctionsSpec.js new file mode 100644 index 000000000000..eb66e6205555 --- /dev/null +++ b/test/ngAnimate/animationHelperFunctionsSpec.js @@ -0,0 +1,135 @@ +'use strict'; + +describe("animation option helper functions", function() { + + beforeEach(module('ngAnimate')); + + var element, applyAnimationClasses; + beforeEach(inject(function($$jqLite) { + applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + element = jqLite('
'); + })); + + describe('prepareAnimationOptions', function() { + it('should construct an options wrapper from the provided options', + inject(function() { + + var options = prepareAnimationOptions({ + value: 'hello' + }); + + expect(options.value).toBe('hello'); + })); + + it('should return the same instance it already instantiated as an options object with the given element', + inject(function() { + + var options = prepareAnimationOptions({}); + expect(prepareAnimationOptions(options)).toBe(options); + + var options2 = {}; + expect(prepareAnimationOptions(options2)).not.toBe(options); + })); + }); + + describe('applyAnimationStyles', function() { + it('should apply the provided `from` styles', inject(function() { + var options = prepareAnimationOptions({ + from: { color: 'maroon' }, + to: { color: 'blue' } + }); + + applyAnimationFromStyles(element, options); + expect(element.attr('style')).toContain('maroon'); + })); + + it('should apply the provided `to` styles', inject(function() { + var options = prepareAnimationOptions({ + from: { color: 'red' }, + to: { color: 'black' } + }); + + applyAnimationToStyles(element, options); + expect(element.attr('style')).toContain('black'); + })); + + it('should apply the both provided `from` and `to` styles', inject(function() { + var options = prepareAnimationOptions({ + from: { color: 'red', 'font-size':'50px' }, + to: { color: 'green' } + }); + + applyAnimationStyles(element, options); + expect(element.attr('style')).toContain('green'); + expect(element.css('font-size')).toBe('50px'); + })); + + it('should only apply the options once', inject(function() { + var options = prepareAnimationOptions({ + from: { color: 'red', 'font-size':'50px' }, + to: { color: 'blue' } + }); + + applyAnimationStyles(element, options); + expect(element.attr('style')).toContain('blue'); + + element.attr('style', ''); + + applyAnimationStyles(element, options); + expect(element.attr('style') || '').toBe(''); + })); + }); + + describe('applyAnimationClasses', function() { + it('should add/remove the provided CSS classes', inject(function() { + element.addClass('four six'); + var options = prepareAnimationOptions({ + addClass: 'one two three', + removeClass: 'four' + }); + + applyAnimationClasses(element, options); + expect(element).toHaveClass('one two three'); + expect(element).toHaveClass('six'); + expect(element).not.toHaveClass('four'); + })); + + it('should add/remove the provided CSS classes only once', inject(function() { + element.attr('class', 'blue'); + var options = prepareAnimationOptions({ + addClass: 'black', + removeClass: 'blue' + }); + + applyAnimationClasses(element, options); + element.attr('class', 'blue'); + + applyAnimationClasses(element, options); + expect(element).toHaveClass('blue'); + expect(element).not.toHaveClass('black'); + })); + }); + + describe('mergeAnimationOptions', function() { + it('should merge in new options', inject(function() { + element.attr('class', 'blue'); + var options = prepareAnimationOptions({ + name: 'matias', + age: 28, + addClass: 'black', + removeClass: 'blue gold' + }); + + mergeAnimationOptions(element, options, { + age: 29, + addClass: 'gold brown', + removeClass: 'orange' + }); + + expect(options.name).toBe('matias'); + expect(options.age).toBe(29); + expect(options.addClass).toBe('black brown'); + expect(options.removeClass).toBe('blue'); + })); + }); +}); diff --git a/test/ngAnimate/animationSpec.js b/test/ngAnimate/animationSpec.js new file mode 100644 index 000000000000..c38f6efd8ea4 --- /dev/null +++ b/test/ngAnimate/animationSpec.js @@ -0,0 +1,858 @@ +'use strict'; + +describe('$$animation', function() { + + beforeEach(module('ngAnimate')); + + var element; + afterEach(function() { + dealoc(element); + }); + + beforeEach(module(function($$animationProvider) { + $$animationProvider.drivers.length = 0; + })); + + it("should not run an animation if there are no drivers", + inject(function($$animation, $$rAF, $rootScope) { + + element = jqLite('
'); + var done = false; + $$animation(element, 'someEvent').then(function() { + done = true; + }); + $$rAF.flush(); + $rootScope.$digest(); + expect(done).toBe(true); + })); + + it("should not run an animation if no drivers return an animation step function", function() { + module(function($$animationProvider, $provide) { + $$animationProvider.drivers.push('matiasDriver'); + $provide.value('matiasDriver', function() { + return false; + }); + }); + inject(function($$animation, $$rAF, $rootScope) { + element = jqLite('
'); + var done = false; + $$animation(element, 'someEvent').then(function() { + done = true; + }); + $rootScope.$digest(); + $$rAF.flush(); + $rootScope.$digest(); + expect(done).toBe(true); + }); + }); + + describe("drivers", function() { + it("should use the first driver that returns a step function", function() { + var count = 0; + var activeDriver; + module(function($$animationProvider, $provide) { + $$animationProvider.drivers.push('1'); + $$animationProvider.drivers.push('2'); + $$animationProvider.drivers.push('3'); + + var runner; + + $provide.value('1', function() { + count++; + }); + + $provide.value('2', function() { + count++; + return { + start: function() { + activeDriver = '2'; + return runner; + } + }; + }); + + $provide.value('3', function() { + count++; + }); + + return function($$AnimateRunner) { + runner = new $$AnimateRunner(); + }; + }); + + inject(function($$animation, $rootScope) { + element = jqLite('
'); + $$animation(element, 'enter'); + $rootScope.$digest(); + + expect(count).toBe(2); + expect(activeDriver).toBe('2'); + }); + }); + + describe('step function', function() { + var capturedAnimation; + beforeEach(module(function($$animationProvider, $provide) { + element = jqLite('
'); + + $$animationProvider.drivers.push('stepper'); + $provide.factory('stepper', function($$AnimateRunner) { + return function() { + capturedAnimation = arguments; + return { + start: function() { + return new $$AnimateRunner(); + } + }; + }; + }); + })); + + it("should obtain the element, event, the provided options and the domOperation", + inject(function($$animation, $rootScope) { + + var options = {}; + options.foo = 'bar'; + options.domOperation = function() { + domOperationCalled = true; + }; + var domOperationCalled = false; + $$animation(element, 'megaEvent', options); + $rootScope.$digest(); + + var details = capturedAnimation[0]; + expect(details.element).toBe(element); + expect(details.event).toBe('megaEvent'); + expect(details.options.foo).toBe(options.foo); + + // the function is wrapped inside of $$animation, but it is still a function + expect(domOperationCalled).toBe(false); + details.options.domOperation(); + expect(domOperationCalled).toBe(true); + })); + + it("should obtain the classes string which is a combination of className, addClass and removeClass", + inject(function($$animation, $rootScope) { + + element.addClass('blue red'); + $$animation(element, 'enter', { + addClass: 'green', + removeClass: 'orange', + tempClasses: 'pink' + }); + + $rootScope.$digest(); + + var classes = capturedAnimation[0].classes; + expect(classes).toBe('blue red green orange pink'); + })); + }); + + it("should traverse the drivers in reverse order", function() { + var log = []; + module(function($$animationProvider, $provide) { + $$animationProvider.drivers.push('first'); + $$animationProvider.drivers.push('second'); + + $provide.value('first', function() { + log.push('first'); + return false; + }); + + $provide.value('second', function() { + log.push('second'); + return false; + }); + }); + + inject(function($$animation, $rootScope) { + element = jqLite('
'); + $$animation(element, 'enter'); + $rootScope.$digest(); + expect(log).toEqual(['second', 'first']); + }); + }); + + they("should $prop the animation call if the driver $proped the returned promise", + ['resolve', 'reject'], function(event) { + + module(function($$animationProvider, $provide) { + $$animationProvider.drivers.push('resolvingAnimation'); + $provide.factory('resolvingAnimation', function($$AnimateRunner) { + return function() { + return { + start: function() { + return new $$AnimateRunner(); + } + }; + }; + }); + }); + + inject(function($$animation, $rootScope, $$rAF) { + var status, element = jqLite('
'); + var runner = $$animation(element, 'enter'); + runner.then(function() { + status = 'resolve'; + }, function() { + status = 'reject'; + }); + + // the animation is started + $rootScope.$digest(); + + event === 'resolve' ? runner.end() : runner.cancel(); + + // the resolve/rejection digest + $$rAF.flush(); + $rootScope.$digest(); + + expect(status).toBe(event); + }); + }); + + they("should $prop the driver animation when runner.$prop() is called", + ['cancel', 'end'], function(method) { + + var log = []; + + module(function($$animationProvider, $provide) { + $$animationProvider.drivers.push('actualDriver'); + $provide.factory('actualDriver', function($$AnimateRunner) { + return function() { + return { + start: function() { + log.push('start'); + return new $$AnimateRunner({ + end: function() { + log.push('end'); + }, + cancel: function() { + log.push('cancel'); + } + }); + } + }; + }; + }); + }); + + inject(function($$animation, $rootScope) { + element = jqLite('
'); + var runner = $$animation(element, 'enter'); + $rootScope.$digest(); + + runner[method](); + expect(log).toEqual(['start', method]); + }); + }); + }); + + describe('when', function() { + var captureLog; + var runnerLog; + var capturedAnimation; + + beforeEach(module(function($$animationProvider, $provide) { + captureLog = []; + runnerLog = []; + capturedAnimation = null; + + $$animationProvider.drivers.push('interceptorDriver'); + $provide.factory('interceptorDriver', function($$AnimateRunner) { + return function(details) { + captureLog.push(capturedAnimation = details); //only one param is passed into the driver + return { + start: function() { + return new $$AnimateRunner({ + end: runnerEvent('end'), + cancel: runnerEvent('cancel') + }); + } + }; + }; + }); + + function runnerEvent(token) { + return function() { + runnerLog.push(token); + }; + } + })); + + describe("singular", function() { + beforeEach(module(function($provide) { + element = jqLite('
'); + return function($rootElement) { + $rootElement.append(element); + }; + })); + + they('should return a runner that object that contains a $prop() function', + ['end', 'cancel', 'then'], function(method) { + inject(function($$animation) { + var runner = $$animation(element, 'someEvent'); + expect(isFunction(runner[method])).toBe(true); + }); + }); + + they('should close the animation if runner.$prop() is called before the $postDigest phase kicks in', + ['end', 'cancel'], function(method) { + inject(function($$animation, $rootScope, $$rAF) { + var status; + var runner = $$animation(element, 'someEvent'); + runner.then(function() { status = 'end'; }, + function() { status = 'cancel'; }); + + runner[method](); + $rootScope.$digest(); + expect(runnerLog).toEqual([]); + + $$rAF.flush(); + expect(status).toBe(method); + }); + }); + + they('should update the runner methods to the ones provided by the driver when the animation starts', + ['end', 'cancel'], function(method) { + + var spy = jasmine.createSpy(); + module(function($$animationProvider, $provide) { + $$animationProvider.drivers.push('animalDriver'); + $provide.factory('animalDriver', function($$AnimateRunner) { + return function() { + return { + start: function() { + var data = {}; + data[method] = spy; + return new $$AnimateRunner(data); + } + }; + }; + }); + }); + inject(function($$animation, $rootScope, $rootElement) { + var r1 = $$animation(element, 'someEvent'); + r1[method](); + expect(spy).not.toHaveBeenCalled(); + $rootScope.$digest(); // this clears the digest which cleans up the mess + + var r2 = $$animation(element, 'otherEvent'); + $rootScope.$digest(); + r2[method](); + expect(spy).toHaveBeenCalled(); + }); + }); + + it('should not start the animation if the element is removed from the DOM before the postDigest kicks in', + inject(function($$animation) { + + var runner = $$animation(element, 'someEvent'); + + expect(capturedAnimation).toBeFalsy(); + element.remove(); + expect(capturedAnimation).toBeFalsy(); + })); + + it('should immediately end the animation if the element is removed from the DOM during the animation', + inject(function($$animation, $$rAF, $rootScope) { + + var runner = $$animation(element, 'someEvent'); + $rootScope.$digest(); + $$rAF.flush(); //the animation is "animating" + + expect(capturedAnimation).toBeTruthy(); + expect(runnerLog).toEqual([]); + element.remove(); + expect(runnerLog).toEqual(['end']); + })); + + it('should not end the animation when the leave animation removes the element from the DOM', + inject(function($$animation, $$rAF, $rootScope) { + + var runner = $$animation(element, 'leave', {}, function() { + element.remove(); + }); + + $rootScope.$digest(); + $$rAF.flush(); //the animation is "animating" + + expect(runnerLog).toEqual([]); + capturedAnimation.options.domOperation(); //this removes the element + element.remove(); + expect(runnerLog).toEqual([]); + })); + + it('should remove the $destroy event listener when the animation is closed', + inject(function($$animation, $$rAF, $rootScope) { + + var addListen = spyOn(element, 'on').andCallThrough(); + var removeListen = spyOn(element, 'off').andCallThrough(); + var runner = $$animation(element, 'someEvent'); + + var args = addListen.mostRecentCall.args[0]; + expect(args).toBe('$destroy'); + + runner.end(); + + args = removeListen.mostRecentCall.args[0]; + expect(args).toBe('$destroy'); + })); + }); + + describe("grouped", function() { + var fromElement; + var toElement; + var fromAnchors; + var toAnchors; + beforeEach(module(function($provide) { + fromElement = jqLite('
'); + toElement = jqLite('
'); + fromAnchors = [ + jqLite('
1
'), + jqLite('
2
'), + jqLite('
3
') + ]; + toAnchors = [ + jqLite('
a
'), + jqLite('
b
'), + jqLite('
c
') + ]; + + return function($rootElement) { + $rootElement.append(fromElement); + $rootElement.append(toElement); + forEach(fromAnchors, function(a) { + fromElement.append(a); + }); + forEach(toAnchors, function(a) { + toElement.append(a); + }); + }; + })); + + it("should group animations together when they have shared anchors and a shared CSS class", + inject(function($$animation, $rootScope) { + + fromElement.addClass('shared-class'); + $$animation(fromElement, 'leave'); + + toElement.addClass('shared-class'); + $$animation(toElement, 'enter'); + + fromAnchors[0].attr('ng-animate-ref', '1'); + toAnchors[0].attr('ng-animate-ref', '1'); + $rootScope.$digest(); + + expect(captureLog.length).toBe(1); + + var fromAnimation = capturedAnimation.from; + expect(fromAnimation.element).toEqual(fromElement); + expect(fromAnimation.event).toBe('leave'); + + var toAnimation = capturedAnimation.to; + expect(toAnimation.element).toBe(toElement); + expect(toAnimation.event).toBe('enter'); + + var fromElm = fromAnchors[0]; + var toElm = toAnchors[0]; + + var anchors = capturedAnimation.anchors[0]; + assertCompareNodes(fromElm, anchors['out']); + assertCompareNodes(toElm, anchors['in']); + })); + + it("should group animations together and properly match up multiple anchors based on their references", + inject(function($$animation, $rootScope) { + + var attr = 'ng-animate-ref'; + + fromAnchors[0].attr(attr, '1'); + fromAnchors[1].attr(attr, '2'); + fromAnchors[2].attr(attr, '3'); + + toAnchors[0].attr(attr, '1'); + toAnchors[1].attr(attr, '3'); + toAnchors[2].attr(attr, '2'); + + fromElement.addClass('shared-class'); + $$animation(fromElement, 'leave'); + + toElement.addClass('shared-class'); + $$animation(toElement, 'enter'); + + $rootScope.$digest(); + + var anchors = capturedAnimation.anchors; + assertCompareNodes(fromAnchors[0], anchors[0]['out']); + assertCompareNodes(toAnchors[0], anchors[0]['in']); + + assertCompareNodes(fromAnchors[1], anchors[1]['out']); + assertCompareNodes(toAnchors[2], anchors[1]['in']); + + assertCompareNodes(fromAnchors[2], anchors[2]['out']); + assertCompareNodes(toAnchors[1], anchors[2]['in']); + })); + + it("should group animations together on the from and to elements if their both contain matching anchors", + inject(function($$animation, $rootScope) { + + fromElement.addClass('shared-class'); + fromElement.attr('ng-animate-ref', '1'); + $$animation(fromElement, 'leave'); + + toElement.addClass('shared-class'); + toElement.attr('ng-animate-ref', '1'); + $$animation(toElement, 'enter'); + + $rootScope.$digest(); + + var anchors = capturedAnimation.anchors[0]; + assertCompareNodes(fromElement, anchors['out']); + assertCompareNodes(toElement, anchors['in']); + })); + + it("should not group animations into an anchored animation if enter/leave events are NOT used", + inject(function($$animation, $rootScope) { + + fromElement.addClass('shared-class'); + fromElement.attr('ng-animate-ref', '1'); + $$animation(fromElement, 'addClass', { + addClass: 'red' + }); + + toElement.addClass('shared-class'); + toElement.attr('ng-animate-ref', '1'); + $$animation(toElement, 'removeClass', { + removeClass: 'blue' + }); + + $rootScope.$digest(); + expect(captureLog.length).toBe(2); + })); + + it("should not group animations together if a matching pair of anchors is not detected", + inject(function($$animation, $rootScope) { + + fromElement.addClass('shared-class'); + $$animation(fromElement, 'leave'); + + toElement.addClass('shared-class'); + $$animation(toElement, 'enter'); + + fromAnchors[0].attr('ng-animate-ref', '6'); + toAnchors[0].attr('ng-animate-ref', '3'); + $rootScope.$digest(); + + expect(captureLog.length).toBe(2); + })); + + it("should not group animations together if a matching CSS class is not detected", + inject(function($$animation, $rootScope) { + + fromElement.addClass('even-class'); + $$animation(fromElement, 'leave'); + + toElement.addClass('odd-class'); + $$animation(toElement, 'enter'); + + fromAnchors[0].attr('ng-animate-ref', '9'); + toAnchors[0].attr('ng-animate-ref', '9'); + $rootScope.$digest(); + + expect(captureLog.length).toBe(2); + })); + + it("should expose the shared CSS class in the options provided to the driver", + inject(function($$animation, $rootScope) { + + fromElement.addClass('fresh-class'); + $$animation(fromElement, 'leave'); + + toElement.addClass('fresh-class'); + $$animation(toElement, 'enter'); + + fromAnchors[0].attr('ng-animate-ref', '9'); + toAnchors[0].attr('ng-animate-ref', '9'); + $rootScope.$digest(); + + expect(capturedAnimation.classes).toBe('fresh-class'); + })); + + it("should update the runner methods to the grouped runner methods handled by the driver", + inject(function($$animation, $rootScope) { + + fromElement.addClass('group-1'); + var runner1 = $$animation(fromElement, 'leave'); + + toElement.addClass('group-1'); + var runner2 = $$animation(toElement, 'enter'); + + expect(runner1).not.toBe(runner2); + + fromAnchors[0].attr('ng-animate-ref', 'abc'); + toAnchors[0].attr('ng-animate-ref', 'abc'); + $rootScope.$digest(); + + expect(runner1).not.toBe(runner2); + expect(runner1.end).toBe(runner2.end); + expect(runner1.cancel).toBe(runner2.cancel); + })); + + they("should end the animation if the $prop element is prematurely removed from the DOM during the animation", ['from', 'to'], function(event) { + inject(function($$animation, $rootScope) { + fromElement.addClass('group-1'); + $$animation(fromElement, 'leave'); + + toElement.addClass('group-1'); + $$animation(toElement, 'enter'); + + fromAnchors[0].attr('ng-animate-ref', 'abc'); + toAnchors[0].attr('ng-animate-ref', 'abc'); + $rootScope.$digest(); + + expect(runnerLog).toEqual([]); + + ('from' ? fromElement : toElement).remove(); + expect(runnerLog).toEqual(['end']); + }); + }); + + it("should not end the animation when the `from` animation calls its own leave dom operation", + inject(function($$animation, $rootScope, $$rAF) { + + fromElement.addClass('group-1'); + var elementRemoved = false; + $$animation(fromElement, 'leave', { + domOperation: function() { + elementRemoved = true; + fromElement.remove(); + } + }); + + toElement.addClass('group-1'); + $$animation(toElement, 'enter'); + + fromAnchors[0].attr('ng-animate-ref', 'abc'); + toAnchors[0].attr('ng-animate-ref', 'abc'); + $rootScope.$digest(); + + var leaveAnimation = capturedAnimation.from; + expect(leaveAnimation.event).toBe('leave'); + + // this removes the element and this code is run normally + // by the driver when it is time for the element to be removed + leaveAnimation.options.domOperation(); + + expect(elementRemoved).toBe(true); + expect(runnerLog).toEqual([]); + })); + + it("should not end the animation if any of the anchor elements are removed from the DOM during the animation", + inject(function($$animation, $rootScope, $$rAF) { + + fromElement.addClass('group-1'); + var elementRemoved = false; + $$animation(fromElement, 'leave', {}, function() { + elementRemoved = true; + fromElement.remove(); + }); + + toElement.addClass('group-1'); + $$animation(toElement, 'enter'); + + fromAnchors[0].attr('ng-animate-ref', 'abc'); + toAnchors[0].attr('ng-animate-ref', 'abc'); + $rootScope.$digest(); + + fromAnchors[0].remove(); + toAnchors[0].remove(); + + expect(runnerLog).toEqual([]); + })); + }); + }); + + describe('[options]', function() { + var runner; + var defered; + var parent; + var mockedDriverFn; + var mockedPlayerFn; + + beforeEach(module(function($$animationProvider, $provide) { + $$animationProvider.drivers.push('mockedTestDriver'); + $provide.factory('mockedTestDriver', function() { + return mockedDriverFn; + }); + + element = jqLite('
'); + parent = jqLite('
'); + + return function($$AnimateRunner, $q, $rootElement, $document) { + jqLite($document[0].body).append($rootElement); + $rootElement.append(parent); + + mockedDriverFn = function(element, method, options, domOperation) { + return { + start: function() { + return runner = new $$AnimateRunner(); + } + }; + }; + }; + })); + + it('should temporarily assign the provided CSS class for the duration of the animation', + inject(function($rootScope, $$animation) { + + $$animation(element, 'enter', { + tempClasses: 'temporary fudge' + }); + $rootScope.$digest(); + + expect(element).toHaveClass('temporary'); + expect(element).toHaveClass('fudge'); + + runner.end(); + $rootScope.$digest(); + + expect(element).not.toHaveClass('temporary'); + expect(element).not.toHaveClass('fudge'); + })); + + it('should add and remove the ng-animate CSS class when the animation is active', + inject(function($$animation, $rootScope) { + + $$animation(element, 'enter'); + $rootScope.$digest(); + expect(element).toHaveClass('ng-animate'); + + runner.end(); + $rootScope.$digest(); + + expect(element).not.toHaveClass('ng-animate'); + })); + + it('should perform the DOM operation at the end of the animation if the driver doesn\'t run it already', + inject(function($$animation, $rootScope) { + + var domOperationFired = false; + $$animation(element, 'enter', { + domOperation: function() { + domOperationFired = true; + } + }); + + $rootScope.$digest(); + + expect(domOperationFired).toBeFalsy(); + runner.end(); + $rootScope.$digest(); + + expect(domOperationFired).toBeTruthy(); + })); + + it('should still apply the `from` and `to` styling even if no driver was detected', function() { + module(function($$animationProvider) { + $$animationProvider.drivers.length = 0; + }); + inject(function($$animation, $rootScope) { + $$animation(element, 'event', { + from: { background: 'red' }, + to: { background: 'blue' } + }); + + expect(element.css('background')).toContain('blue'); + }); + }); + + it('should still apply the `from` and `to` styling even if the driver does not do the job', function() { + module(function($$animationProvider, $provide) { + $$animationProvider.drivers[0] = 'dumbDriver'; + $provide.factory('dumbDriver', function($q) { + return function stepFn() { + return $q.when(true); + }; + }); + }); + inject(function($$animation, $rootScope, $$rAF) { + element.addClass('four'); + + var completed = false; + $$animation(element, 'event', { + from: { background: 'red' }, + to: { background: 'blue', 'font-size': '50px' } + }).then(function() { + completed = true; + }); + + $rootScope.$digest(); //runs the animation + $rootScope.$digest(); //flushes the step code + $$rAF.flush(); //runs the $$animation promise + $rootScope.$digest(); //the runner promise + + expect(completed).toBe(true); + expect(element.css('background')).toContain('blue'); + expect(element.css('font-size')).toBe('50px'); + }); + }); + + it('should still resolve the `addClass` and `removeClass` classes even if no driver was detected', function() { + module(function($$animationProvider) { + $$animationProvider.drivers.length = 0; + }); + inject(function($$animation, $rootScope) { + element.addClass('four'); + + $$animation(element, 'event', { + addClass: 'one two three', + removeClass: 'four' + }); + + expect(element).toHaveClass('one'); + expect(element).toHaveClass('two'); + expect(element).toHaveClass('three'); + expect(element).not.toHaveClass('four'); + }); + }); + + it('should still resolve the `addClass` and `removeClass` classes even if the driver does not do the job', function() { + module(function($$animationProvider, $provide) { + $$animationProvider.drivers[0] = 'dumbDriver'; + $provide.factory('dumbDriver', function($$AnimateRunner) { + return function initFn() { + return function stepFn() { + return new $$AnimateRunner(); + }; + }; + }); + }); + inject(function($$animation, $rootScope, $$rAF) { + element.addClass('four'); + + var completed = false; + var runner = $$animation(element, 'event', { + addClass: 'one two three', + removeClass: 'four' + }); + runner.then(function() { + completed = true; + }); + + $rootScope.$digest(); //runs the animation + $rootScope.$digest(); //flushes the step code + + runner.end(); + $$rAF.flush(); //runs the $$animation promise + $rootScope.$digest(); //the runner promise + + expect(completed).toBe(true); + expect(element).toHaveClass('one'); + expect(element).toHaveClass('two'); + expect(element).toHaveClass('three'); + expect(element).not.toHaveClass('four'); + }); + }); + }); +}); diff --git a/test/ngRoute/directive/ngViewSpec.js b/test/ngRoute/directive/ngViewSpec.js index c910ba509b0d..d86046095ac4 100644 --- a/test/ngRoute/directive/ngViewSpec.js +++ b/test/ngRoute/directive/ngViewSpec.js @@ -813,7 +813,7 @@ describe('ngView animations', function() { }); }); - inject(function($rootScope, $compile, $location, $route, $timeout, $rootElement, $sniffer, $animate) { + inject(function($rootScope, $compile, $location, $route, $timeout, $rootElement, $sniffer, $animate, $$rAF) { element = $compile(html('
'))($rootScope); $animate.enabled(true); @@ -837,6 +837,8 @@ describe('ngView animations', function() { expect($animate.queue.shift().event).toBe('enter'); //ngRepeat 3 expect($animate.queue.shift().event).toBe('enter'); //ngRepeat 4 + $$rAF.flush(); + expect(element.text()).toEqual('34'); function n(text) { From 2953d794ee33fcb2b713af4c752fcc1e2f33fac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Fri, 10 Apr 2015 10:43:28 -0700 Subject: [PATCH 188/489] docs(CHANGELOG): add changes for 1.4.0-rc.0 --- CHANGELOG.md | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18891fa8bed7..de3029f88254 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,161 @@ + +# v1.4.0-rc.0 smooth-unwinding (2015-04-10) + + +## Bug Fixes + +- **$compile:** + - throw error on invalid directive name + ([170ff9a3](https://github.com/angular/angular.js/commit/170ff9a37dea8772dda7c89e84176ac1a8992878), + [#11281](https://github.com/angular/angular.js/issues/11281), [#11109](https://github.com/angular/angular.js/issues/11109)) + - update data() when controller returns custom value + ([9900610e](https://github.com/angular/angular.js/commit/9900610eea4ece87b063f2aa9d82c75c369927df), + [#11147](https://github.com/angular/angular.js/issues/11147), [#11326](https://github.com/angular/angular.js/issues/11326)) +- **$http:** throw error if `success` and `error` methods do not receive a function + ([1af563d4](https://github.com/angular/angular.js/commit/1af563d43e74cb7be53e815b66fd91dd93986ed6), + [#11330](https://github.com/angular/angular.js/issues/11330), [#11333](https://github.com/angular/angular.js/issues/11333)) +- **$parse:** fix parse errors on older Android WebViews which choke with reserved keywords + ([10ae33b2](https://github.com/angular/angular.js/commit/10ae33b2d88b04df76f519edc50a47fa30f83e96), + [#11455](https://github.com/angular/angular.js/issues/11455)) +- **$rootScope:** allow destroying a root scope + ([f8c8cf69](https://github.com/angular/angular.js/commit/f8c8cf698aa23640249d79fd405605694478e4f7), + [#11241](https://github.com/angular/angular.js/issues/11241), [#10895](https://github.com/angular/angular.js/issues/10895)) +- **cookieReader:** safely access $document so it can be mocked + ([a057e089](https://github.com/angular/angular.js/commit/a057e0896a7fe2fdaba50b2515555b86e4f4be27), + [#11373](https://github.com/angular/angular.js/issues/11373), [#11388](https://github.com/angular/angular.js/issues/11388)) +- **filterFilter:** fix matching against `null`/`undefined` + ([b5002ab6](https://github.com/angular/angular.js/commit/b5002ab62ad6e13f4339e20106e1fdece14912a2), + [#11432](https://github.com/angular/angular.js/issues/11432), [#11445](https://github.com/angular/angular.js/issues/11445)) +- **ngAnimate:** ensure that minified repaint code isn't removed + ([c55a4944](https://github.com/angular/angular.js/commit/c55a494433e619aad0c7ef9fddadc0b3fdf53915), + [#9936](https://github.com/angular/angular.js/issues/9936)) +- **ngAria:** handle elements with role="checkbox/menuitemcheckbox" + ([44337f63](https://github.com/angular/angular.js/commit/44337f63fa94116795e83e3a764a6ba6782809c7), + [#11317](https://github.com/angular/angular.js/issues/11317), [#11321](https://github.com/angular/angular.js/issues/11321)) +- **ngModel:** allow setting model to NaN when asyncValidator is present + ([948120ec](https://github.com/angular/angular.js/commit/948120ecdbc4dd07880c0107564c50c7675b8a93), + [#11315](https://github.com/angular/angular.js/issues/11315), [#11411](https://github.com/angular/angular.js/issues/11411)) +- **ngTouch:** register touches properly when jQuery is used + ([06a9f0a9](https://github.com/angular/angular.js/commit/06a9f0a95f0e72fa2e9879fe8a49e9bf69986a5f), + [#4001](https://github.com/angular/angular.js/issues/4001), [#8584](https://github.com/angular/angular.js/issues/8584), [#10797](https://github.com/angular/angular.js/issues/10797), [#11488](https://github.com/angular/angular.js/issues/11488)) +- **select:** don't call $render twice if $viewValue ref changes + ([7e5c447f](https://github.com/angular/angular.js/commit/7e5c447fa9ad7d81cc818d6e79392c3e4a6b23a0), + [#11329](https://github.com/angular/angular.js/issues/11329), [#11412](https://github.com/angular/angular.js/issues/11412)) + + +## Features + +- **$anchorScroll:** allow scrolling to a specified element + ([731c8b5e](https://github.com/angular/angular.js/commit/731c8b5e2d01a44aa91f967f1a6acbadb8005a8b), + [#4568](https://github.com/angular/angular.js/issues/4568), [#9596](https://github.com/angular/angular.js/issues/9596)) +- **$animate:** complete refactor of internal animation code + ([c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef)) +- **$http:** support custom params serializers + ([6c8464ad](https://github.com/angular/angular.js/commit/6c8464ad14dd308349f632245c1a064c9aae242a), + [#3740](https://github.com/angular/angular.js/issues/3740), [#7429](https://github.com/angular/angular.js/issues/7429), [#9224](https://github.com/angular/angular.js/issues/9224), [#11461](https://github.com/angular/angular.js/issues/11461)) +- **$interpolate:** extend interpolation with MessageFormat like syntax + ([1e58488a](https://github.com/angular/angular.js/commit/1e58488ad65abf7031bab5813523bb9d86dbd28c), + [#11152](https://github.com/angular/angular.js/issues/11152)) +- **angular.Module:** add `decorator` method + ([e57138d7](https://github.com/angular/angular.js/commit/e57138d7eff1210f99238c475fff57530bf0ab19), + [#11305](https://github.com/angular/angular.js/issues/11305), [#11300](https://github.com/angular/angular.js/issues/11300)) +- **ngClass:** add support for conditional map within an array. + ([4588e627](https://github.com/angular/angular.js/commit/4588e627bb7238b2113241919b948d0e5166c76d), + [#4807](https://github.com/angular/angular.js/issues/4807)) +- **travis:** run unit tests on iOS 8 + ([2cdb2016](https://github.com/angular/angular.js/commit/2cdb2016b9d89abfb5ab988b67d5f26f3bf21908), + [#11479](https://github.com/angular/angular.js/issues/11479)) + + +## Performance Improvements + +- **$rootScope:** remove history event handler when app is torn down + ([d996305b](https://github.com/angular/angular.js/commit/d996305b4470f80fbb1cbddf54b7d10ffbb6ab47), + [#9897](https://github.com/angular/angular.js/issues/9897), [#9905](https://github.com/angular/angular.js/issues/9905)) +- **benchmark:** add ngmodel benchmarks to largetable-bp + ([b8dbdb0c](https://github.com/angular/angular.js/commit/b8dbdb0c5e2cd176c6d94d60f781cfc02e646592), + [#11082](https://github.com/angular/angular.js/issues/11082)) +- **ngOptions:** only perform deep equality check on ngModel if using track by + ([171b9f7f](https://github.com/angular/angular.js/commit/171b9f7f2339ef9047b8526b2c3f36bb58d14feb), + [#11448](https://github.com/angular/angular.js/issues/11448), [#11447](https://github.com/angular/angular.js/issues/11447)) + + +## Breaking Changes + +- **$animate:** due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef), + JavaSript and CSS animations can no longer be run in +parallel. With earlier versions of ngAnimate, both CSS and JS animations +would be run together when multiple animations were detected. This +feature has now been removed, however, the same effect, with even more +possibilities, can be achieved by injecting `$animateCss` into a +JavaScript-defined animation and creating custom CSS-based animations +from there. Read the ngAnimate docs for more info. + +- **$animate:** due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef), + The function params for `$animate.enabled()` when an +element is used are now flipped. This fix allows the function to act as +a getter when a single element param is provided. + +```js +// < 1.4 +$animate.enabled(false, element); + +// 1.4+ +$animate.enabled(element, false); +``` + +- **$animate:** due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef), + In addition to disabling the children of the element, +`$animate.enabled(element, false)` will now also disable animations on +the element itself. + +- **$animate:** due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef), + Animation-related callbacks are now fired on +`$animate.on` instead of directly being on the element. + +```js +// < 1.4 +element.on('$animate:before', function(e, data) { + if (data.event === 'enter') { ... } +}); +element.off('$animate:before', fn); + +// 1.4+ +$animate.on(element, 'enter', function(data) { + //... +}); +$animate.off(element, 'enter', fn); +``` + +- **$animate:** due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef), + There is no need to call `$scope.$apply` or +`$scope.$digest` inside of a animation promise callback anymore +since the promise is resolved within a digest automatically (but a +digest is not run unless the promise is chained). + +```js +// < 1.4 +$animate.enter(element).then(function() { + $scope.$apply(function() { + $scope.explode = true; + }); +}); + +// 1.4+ +$animate.enter(element).then(function() { + $scope.explode = true; +}); +``` + +- **$animate:** due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef), + When an enter, leave or move animation is triggered then it +will always end any pending or active parent class based animations +(animations triggered via ngClass) in order to ensure that any CSS +styles are resolved in time. + + + + # 1.4.0-beta.6 cookie-liberation (2015-03-17) From 0cb8f28ab7c9d0dc36221a4209b1817c8bce4f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Fri, 10 Apr 2015 13:32:27 -0700 Subject: [PATCH 189/489] fix(ngAnimate): ensure SVG classes are properly removed --- src/ngAnimate/shared.js | 1 - test/ngAnimate/animateCssSpec.js | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ngAnimate/shared.js b/src/ngAnimate/shared.js index 985d4d170109..eb83dc87e341 100644 --- a/src/ngAnimate/shared.js +++ b/src/ngAnimate/shared.js @@ -110,7 +110,6 @@ function applyAnimationClassesFactory($$jqLite) { } if (options.removeClass) { $$removeClass($$jqLite, element, options.removeClass); - element.removeClass(options.removeClass); options.removeClass = null; } } diff --git a/test/ngAnimate/animateCssSpec.js b/test/ngAnimate/animateCssSpec.js index afcc52efbf40..b0dce41c7203 100644 --- a/test/ngAnimate/animateCssSpec.js +++ b/test/ngAnimate/animateCssSpec.js @@ -2421,7 +2421,8 @@ describe("ngAnimate $animateCss", function() { duration: 0 }); - expect(child.attr('class')).toBe(''); + var className = child[0].getAttribute('class'); + expect(className).toBe(''); })); }); }); From 25e4d1df5c45dbc0f1e1743046aebb23af78183a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Fri, 10 Apr 2015 14:10:24 -0700 Subject: [PATCH 190/489] docs($animateCss): remove out-dated return type details --- src/ngAnimate/animateCss.js | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/ngAnimate/animateCss.js b/src/ngAnimate/animateCss.js index 1280da9b714b..641f07449287 100644 --- a/src/ngAnimate/animateCss.js +++ b/src/ngAnimate/animateCss.js @@ -169,19 +169,7 @@ * start: Function, * * // ends (aborts) the animation - * end: Function, - * - * // the total number of seconds that the animation will run for - * duration: Number, - * - * // the total number of seconds that the animation will delay for before starting - * delay: Number, - * - * // whether or not transitions were detected and will therefore be used for the animation - * transitions: Boolean, - * - * // whether or not keyframe animations were detected and will therefore be used for the animation - * keyframes: Boolean + * end: Function * } * ``` * From be616bcb33413939ed4bc3e5c9e8526d2e5cafcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Fri, 10 Apr 2015 14:17:00 -0700 Subject: [PATCH 191/489] docs(ngAnimate): update broken callback ngView example --- src/ngAnimate/module.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ngAnimate/module.js b/src/ngAnimate/module.js index f5e90a9fd7b2..f41d2818feaf 100644 --- a/src/ngAnimate/module.js +++ b/src/ngAnimate/module.js @@ -467,12 +467,12 @@ * anymore.) * * In addition to the animation promise, we can also make use of animation-related callbacks within our directives and controller code by registering - * an event listener using the `$animate` service. Let's say for example that an animation was triggered on our `ng-view` element and we wanted our + * an event listener using the `$animate` service. Let's say for example that an animation was triggered on our view * routing controller to hook into that: * * ```js * ngModule.controller('HomePageController', ['$animate', function($animate) { - * $animate.on('enter', '[ng-view]', function(element) { + * $animate.on('enter', ngViewElement, function(element) { * // the animation for this route has completed * }]); * }]) From ed27bb2f656b45d6956a5d0d79efa874c057269f Mon Sep 17 00:00:00 2001 From: cexbrayat Date: Tue, 7 Apr 2015 16:18:28 +0800 Subject: [PATCH 192/489] docs(ngMessages): missing quote in sample Closes #11527 --- src/ngMessages/messages.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ngMessages/messages.js b/src/ngMessages/messages.js index 5f62858640cb..5e87a7d4dc71 100644 --- a/src/ngMessages/messages.js +++ b/src/ngMessages/messages.js @@ -159,7 +159,7 @@ var jqLite = angular.element; * required /> *
*
You did not enter your email address
- *
+ *
* Your email must be between 5 and 100 characters long *
*
From 05afb5f601db45d08f8926ffc7453a002b213c6b Mon Sep 17 00:00:00 2001 From: Marcy Sutton Date: Mon, 16 Feb 2015 16:28:22 -0800 Subject: [PATCH 193/489] docs(): better accessibility in docs examples Closes #11079 --- src/ng/compile.js | 6 +- src/ng/directive/attrs.js | 24 ++-- src/ng/directive/input.js | 196 +++++++++++++++++++------------ src/ng/directive/ngBind.js | 6 +- src/ng/directive/ngClass.js | 31 +++-- src/ng/directive/ngController.js | 28 ++--- src/ng/directive/ngIf.js | 2 +- src/ng/directive/ngList.js | 6 +- src/ng/directive/ngModel.js | 68 ++++++----- src/ng/directive/ngOptions.js | 35 +++--- src/ng/directive/ngPluralize.js | 6 +- src/ng/directive/ngRepeat.js | 2 +- src/ng/directive/ngShowHide.js | 4 +- src/ng/directive/ngTransclude.js | 4 +- src/ng/filter/filter.js | 10 +- src/ng/filter/filters.js | 4 +- src/ng/filter/limitTo.js | 15 ++- src/ng/http.js | 4 +- src/ng/interval.js | 2 +- src/ng/log.js | 4 +- src/ng/sce.js | 2 +- src/ng/window.js | 2 +- src/ngMessages/messages.js | 95 ++++++++------- 23 files changed, 327 insertions(+), 229 deletions(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index 1268cbc59a9a..0aba65aec107 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -621,8 +621,8 @@ }]);
-
-
+
+
@@ -659,7 +659,7 @@ * * `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: + * 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. diff --git a/src/ng/directive/attrs.js b/src/ng/directive/attrs.js index e22a7892e4e9..6854df03aaf6 100644 --- a/src/ng/directive/attrs.js +++ b/src/ng/directive/attrs.js @@ -113,12 +113,12 @@ * * The buggy way to write it: * ```html - * + * Description * ``` * * The correct way to write it: * ```html - * + * Description * ``` * * @element IMG @@ -139,12 +139,12 @@ * * The buggy way to write it: * ```html - * + * Description * ``` * * The correct way to write it: * ```html - * + * Description * ``` * * @element IMG @@ -181,7 +181,7 @@ * @example - Click me to toggle:
+
@@ -216,8 +216,8 @@ * @example - Check me to check both:
- +
+
it('should check both checkBoxes', function() { @@ -251,8 +251,8 @@ * @example - Check me to make text readonly:
- +
+
it('should toggle readonly attr', function() { @@ -287,8 +287,8 @@ * @example - Check me to select:
-
+ @@ -324,7 +324,7 @@ * @example - Check me check multiple:
+
Show/Hide me
diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index e9b781bcf320..778eda83eda0 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -68,13 +68,16 @@ var inputType = { }]);
- Single word: - - Required! - - Single word only! - + +
+ + Required! + + Single word only! +
text = {{example.text}}
myForm.input.$valid = {{myForm.input.$valid}}
myForm.input.$error = {{myForm.input.$error}}
@@ -153,13 +156,15 @@ var inputType = { }]); - Pick a date in 2013: + - - Required! - - Not a valid date! +
+ + Required! + + Not a valid date! +
value = {{example.value | date: "yyyy-MM-dd"}}
myForm.input.$valid = {{myForm.input.$valid}}
myForm.input.$error = {{myForm.input.$error}}
@@ -246,13 +251,15 @@ var inputType = { }]); - Pick a date between in 2013: + - - Required! - - Not a valid date! +
+ + Required! + + Not a valid date! +
value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}
myForm.input.$valid = {{myForm.input.$valid}}
myForm.input.$error = {{myForm.input.$error}}
@@ -340,13 +347,15 @@ var inputType = { }]); - Pick a between 8am and 5pm: + - - Required! - - Not a valid date! +
+ + Required! + + Not a valid date! +
value = {{example.value | date: "HH:mm:ss"}}
myForm.input.$valid = {{myForm.input.$valid}}
myForm.input.$error = {{myForm.input.$error}}
@@ -433,13 +442,17 @@ var inputType = { }]); - Pick a date between in 2013: - - - Required! - - Not a valid date! + +
+ + Required! + + Not a valid date! +
value = {{example.value | date: "yyyy-Www"}}
myForm.input.$valid = {{myForm.input.$valid}}
myForm.input.$error = {{myForm.input.$error}}
@@ -526,13 +539,15 @@ var inputType = { }]); - Pick a month in 2013: + - - Required! - - Not a valid month! +
+ + Required! + + Not a valid month! +
value = {{example.value | date: "yyyy-MM"}}
myForm.input.$valid = {{myForm.input.$valid}}
myForm.input.$error = {{myForm.input.$error}}
@@ -629,12 +644,16 @@ var inputType = { }]); - Number: - - Required! - - Not valid number! + +
+ + Required! + + Not valid number! +
value = {{example.value}}
myForm.input.$valid = {{myForm.input.$valid}}
myForm.input.$error = {{myForm.input.$error}}
@@ -719,11 +738,15 @@ var inputType = { }]); - URL: - - Required! - - Not valid url! +
diff --git a/src/ng/directive/ngBind.js b/src/ng/directive/ngBind.js index 8f47eacfead0..37660a75ba52 100644 --- a/src/ng/directive/ngBind.js +++ b/src/ng/directive/ngBind.js @@ -35,7 +35,7 @@ }]);
- Enter name:
+
Hello !
@@ -96,8 +96,8 @@ var ngBindDirective = ['$compile', function($compile) { }]);
- Salutation:
- Name:
+
+

        
diff --git a/src/ng/directive/ngClass.js b/src/ng/directive/ngClass.js index af8d07388cd7..cd1f6241efd3 100644 --- a/src/ng/directive/ngClass.js +++ b/src/ng/directive/ngClass.js @@ -161,21 +161,34 @@ function classDirective(name, selector) {

Map Syntax Example

- deleted (apply "strike" class)
- important (apply "bold" class)
- error (apply "red" class) +
+
+

Using String Syntax

- +

Using Array Syntax

-
-
-
+
+
+

Using Array and Map Syntax

-
- warning (apply "orange" class) +
+
.strike { diff --git a/src/ng/directive/ngController.js b/src/ng/directive/ngController.js index e759d2b5c1b2..a0eb57ea94cf 100644 --- a/src/ng/directive/ngController.js +++ b/src/ng/directive/ngController.js @@ -64,20 +64,20 @@ * * *
- * Name: - * [ greet ]
+ * + *
* Contact: *
    *
  • - * * * * - * - * [ clear - * | X ] + * + * + * *
  • - *
  • [ add ]
  • + *
  • *
*
*
@@ -147,20 +147,20 @@ * * *
- * Name: - * [ greet ]
+ * + *
* Contact: *
    *
  • - * * * * - * - * [ clear - * | X ] + * + * + * *
  • - *
  • [ add ]
  • + *
  • [ ]
  • *
*
*
diff --git a/src/ng/directive/ngIf.js b/src/ng/directive/ngIf.js index 5ad6c1d66ca1..8a1f7ee0153d 100644 --- a/src/ng/directive/ngIf.js +++ b/src/ng/directive/ngIf.js @@ -46,7 +46,7 @@ * @example - Click me:
+
Show when checked: This is removed when the checkbox is unchecked. diff --git a/src/ng/directive/ngList.js b/src/ng/directive/ngList.js index 7415336cc266..0b48853eb07d 100644 --- a/src/ng/directive/ngList.js +++ b/src/ng/directive/ngList.js @@ -30,9 +30,11 @@ *
* *
- * List: - * + * + * + * * Required! + * *
* names = {{names}}
* myForm.namesInput.$valid = {{myForm.namesInput.$valid}}
diff --git a/src/ng/directive/ngModel.js b/src/ng/directive/ngModel.js index a3446c7ff1a9..119ca7a6f98d 100644 --- a/src/ng/directive/ngModel.js +++ b/src/ng/directive/ngModel.js @@ -192,7 +192,7 @@ is set to `true`. The parse error is stored in `ngModel.$error.parse`. required>Change me!
Required!
- + @@ -474,12 +474,14 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ *

Now see what happens if you start typing then press the Escape key

* *
- *

With $rollbackViewValue()

- *
+ *

With $rollbackViewValue()

+ *
* myValue: "{{ myValue }}" * - *

Without $rollbackViewValue()

- *
+ *

Without $rollbackViewValue()

+ *
* myValue: "{{ myValue }}" *
*
@@ -943,10 +945,13 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ background: red; } - Update input to see transitions when valid/invalid. - Integer is a valid value. +

+ Update input to see transitions when valid/invalid. + Integer is a valid value. +

- +
* @@ -976,10 +981,11 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
- Name: - +
user.name = 
@@ -1115,14 +1121,15 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
- Name: -
- - Other data: -
+
+
user.name = 
@@ -1170,11 +1177,13 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
- Name: - -
+ + +
user.name = 
@@ -1193,10 +1202,11 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
- Name: - +
user.name = 
diff --git a/src/ng/directive/ngOptions.js b/src/ng/directive/ngOptions.js index a612613698cd..8c9ec905764f 100644 --- a/src/ng/directive/ngOptions.js +++ b/src/ng/directive/ngOptions.js @@ -148,37 +148,40 @@ var ngOptionsMinErr = minErr('ngOptions');
  • - Name: - Disabled? - [X] + + +
  • - [add] +

- Color (null not allowed): -
- - Color (null allowed): +
+
- Color grouped by shade: -
+
- Color grouped by shade, with some disabled: - -
+ +
- Select bogus.
+ Select . +

Currently selected: {{ {selected_color:myColor} }}
- Person 1:
- Person 2:
- Number of People:
+
+
+
Without Offset: diff --git a/src/ng/directive/ngRepeat.js b/src/ng/directive/ngRepeat.js index 04b9726aa9dd..06180f7022ce 100644 --- a/src/ng/directive/ngRepeat.js +++ b/src/ng/directive/ngRepeat.js @@ -216,7 +216,7 @@ {name:'Samantha', age:60, gender:'girl'} ]"> I have {{friends.length}} friends. They are: - +
  • [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old. diff --git a/src/ng/directive/ngShowHide.js b/src/ng/directive/ngShowHide.js index dad6f8911f23..4f61a984bcd8 100644 --- a/src/ng/directive/ngShowHide.js +++ b/src/ng/directive/ngShowHide.js @@ -98,7 +98,7 @@ var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate'; * @example - Click me:
    + Click me:
    Show:
    @@ -263,7 +263,7 @@ var ngShowDirective = ['$animate', function($animate) { * @example - Click me:
    + Click me:
    Show:
    diff --git a/src/ng/directive/ngTransclude.js b/src/ng/directive/ngTransclude.js index 4dd391ae5e93..36201a69ab73 100644 --- a/src/ng/directive/ngTransclude.js +++ b/src/ng/directive/ngTransclude.js @@ -34,8 +34,8 @@ }]);
    -
    -
    +
    +
    {{text}}
    diff --git a/src/ng/filter/filter.js b/src/ng/filter/filter.js index 6e29e2cf5a87..949b44f21edf 100644 --- a/src/ng/filter/filter.js +++ b/src/ng/filter/filter.js @@ -67,7 +67,7 @@ {name:'Julie', phone:'555-8765'}, {name:'Juliette', phone:'555-5678'}]">
    - Search: + @@ -76,10 +76,10 @@
    NamePhone

    - Any:
    - Name only
    - Phone only
    - Equality
    +
    +
    +
    +
    diff --git a/src/ng/filter/filters.js b/src/ng/filter/filters.js index 77c04bdc58a2..fe49719ffa82 100644 --- a/src/ng/filter/filters.js +++ b/src/ng/filter/filters.js @@ -25,7 +25,7 @@ }]);
    -
    +
    default currency symbol ($): {{amount | currency}}
    custom currency identifier (USD$): {{amount | currency:"USD$"}} no fractions (0): {{amount | currency:"USD$":0}} @@ -100,7 +100,7 @@ function currencyFilter($locale) { }]);
    - Enter number:
    +
    Default formatting: {{val | number}}
    No fractions: {{val | number:0}}
    Negative number: {{-val | number:4}} diff --git a/src/ng/filter/limitTo.js b/src/ng/filter/limitTo.js index 02e227686ded..a42ec8caf40f 100644 --- a/src/ng/filter/limitTo.js +++ b/src/ng/filter/limitTo.js @@ -37,11 +37,20 @@ }]);
    - Limit {{numbers}} to: +

    Output numbers: {{ numbers | limitTo:numLimit }}

    - Limit {{letters}} to: +

    Output letters: {{ letters | limitTo:letterLimit }}

    - Limit {{longNumber}} to: +

    Output long number: {{ longNumber | limitTo:longNumberLimit }}

    diff --git a/src/ng/http.js b/src/ng/http.js index 75991b20c57c..e4910219ff51 100644 --- a/src/ng/http.js +++ b/src/ng/http.js @@ -746,11 +746,11 @@ function $HttpProvider() {
    - - +
    diff --git a/src/ng/sce.js b/src/ng/sce.js index 65cdcb4c5138..db87dc0a8d04 100644 --- a/src/ng/sce.js +++ b/src/ng/sce.js @@ -424,7 +424,7 @@ function $SceDelegateProvider() { * Here's an example of a binding in a privileged context: * * ``` - * + * *
    * ``` * diff --git a/src/ng/window.js b/src/ng/window.js index 9a2637973bd8..1b0ebb0d3bbc 100644 --- a/src/ng/window.js +++ b/src/ng/window.js @@ -28,7 +28,7 @@ }]);
    - +
    diff --git a/src/ngMessages/messages.js b/src/ngMessages/messages.js index 5e87a7d4dc71..aa3f0366b83f 100644 --- a/src/ngMessages/messages.js +++ b/src/ngMessages/messages.js @@ -31,8 +31,11 @@ var jqLite = angular.element; * * ```html *
    - * - *
    + * + *
    *
    You did not enter a field
    *
    * Your email must be between 5 and 100 characters long @@ -80,7 +83,7 @@ var jqLite = angular.element; *
    This field is too short
    * * - *
    + *
    *
    *
    * ``` @@ -97,16 +100,18 @@ var jqLite = angular.element; * * * - * - * + * * - *
    + *
    * *
    You did not enter your email address
    * @@ -131,13 +136,15 @@ var jqLite = angular.element; * * ```html * - * - * - *
    + * + *
    *
    You did not enter your email address
    *
    * @@ -151,13 +158,16 @@ var jqLite = angular.element; * that multiple errors can be associated with a single error message: * * ```html - * - *
    + * + *
    *
    You did not enter your email address
    *
    * Your email must be between 5 and 100 characters long @@ -172,7 +182,7 @@ var jqLite = angular.element; * directive. * * ```html - *
    + *
    *
    *
    Please enter something
    *
    @@ -192,7 +202,7 @@ var jqLite = angular.element; * Let's say that our HTML code for our messages container looks like so: * * ```html - *
    + * @@ -258,14 +268,14 @@ angular.module('ngMessages', []) * @usage * ```html * - * + * * ... * ... * ... * * * - * + * ... * ... * ... @@ -282,17 +292,18 @@ angular.module('ngMessages', []) * animations="true" fixBase="true"> * * - * - * - * + * *
    myForm.myName.$error = {{ myForm.myName.$error | json }}
    * - *
    + *
    You did not enter a field
    *
    Your field is too short
    *
    Your field is too long
    @@ -481,12 +492,12 @@ angular.module('ngMessages', []) * @usage * ```html * - * + * ... * * * - * + * ... * * ``` @@ -537,13 +548,13 @@ angular.module('ngMessages', []) * @usage * ```html * - * + * ... * ... * * * - * + * ... * ... * From 3a0bef09411725d30847a683b192d6dffe7d38ce Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Tue, 14 Apr 2015 21:54:55 +0100 Subject: [PATCH 194/489] docs(ngController): fix e2e test The changes made in 2a156c2d7ec825ff184480de9aac4b0d7fbd5275 caused this test to fail. The test was trying to find an anchor with specified text but the anchor had changed to a button. --- src/ng/directive/ngController.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ng/directive/ngController.js b/src/ng/directive/ngController.js index a0eb57ea94cf..fe742d7d6ca7 100644 --- a/src/ng/directive/ngController.js +++ b/src/ng/directive/ngController.js @@ -127,12 +127,12 @@ * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value')) * .toBe('john.smith@example.org'); * - * firstRepeat.element(by.linkText('clear')).click(); + * firstRepeat.element(by.buttonText('clear')).click(); * * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value')) * .toBe(''); * - * container.element(by.linkText('add')).click(); + * container.element(by.buttonText('add')).click(); * * expect(container.element(by.repeater('contact in settings.contacts').row(2)) * .element(by.model('contact.value')) @@ -210,12 +210,12 @@ * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value')) * .toBe('john.smith@example.org'); * - * firstRepeat.element(by.linkText('clear')).click(); + * firstRepeat.element(by.buttonText('clear')).click(); * * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value')) * .toBe(''); * - * container.element(by.linkText('add')).click(); + * container.element(by.buttonText('add')).click(); * * expect(container.element(by.repeater('contact in contacts').row(2)) * .element(by.model('contact.value')) From 9e0a092ee08e3851eb634516188ab9b7703920d5 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Tue, 14 Apr 2015 22:08:57 +0100 Subject: [PATCH 195/489] docs(input[week]): add id to input element to fix e2e test --- src/ng/directive/input.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 778eda83eda0..a4d87a0adf7b 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -443,7 +443,7 @@ var inputType = { From 85bb261ed7b50ab159f862465337b1a5d2cf4622 Mon Sep 17 00:00:00 2001 From: Chirayu Krishnappa Date: Tue, 14 Apr 2015 12:17:37 -0700 Subject: [PATCH 196/489] fix(ngMessageFormat): minified symbol and nested required expression Add an E2E test that works against the minified module to test that the minified build works correctly. Fix a bug where mustHaveExpression was passed through to submessages unchanged. Use of the messageFormat syntax automatically means that you are using an expression. Therefore, submessages should not be required to also have messages. Closes #11414 Closes #11592 --- src/ngMessageFormat/messageFormatCommon.js | 8 +-- src/ngMessageFormat/messageFormatParser.js | 2 +- src/ngMessageFormat/messageFormatService.js | 54 ++++++++++++++++++++- test/ngMessageFormat/messageFormatSpec.js | 8 +-- 4 files changed, 62 insertions(+), 10 deletions(-) diff --git a/src/ngMessageFormat/messageFormatCommon.js b/src/ngMessageFormat/messageFormatCommon.js index b8870ed4fe57..7831c82b1924 100644 --- a/src/ngMessageFormat/messageFormatCommon.js +++ b/src/ngMessageFormat/messageFormatCommon.js @@ -5,11 +5,11 @@ // This file is compiled with Closure compiler's ADVANCED_OPTIMIZATIONS flag! Be wary of using // constructs incompatible with that mode. -var $interpolateMinErr = angular['$interpolateMinErr']; +var $interpolateMinErr = window['angular']['$interpolateMinErr']; -var noop = angular['noop'], - isFunction = angular['isFunction'], - toJson = angular['toJson']; +var noop = window['angular']['noop'], + isFunction = window['angular']['isFunction'], + toJson = window['angular']['toJson']; function stringify(value) { if (value == null /* null/undefined */) { return ''; } diff --git a/src/ngMessageFormat/messageFormatParser.js b/src/ngMessageFormat/messageFormatParser.js index 66b94bcba40b..75327ffedc80 100644 --- a/src/ngMessageFormat/messageFormatParser.js +++ b/src/ngMessageFormat/messageFormatParser.js @@ -334,7 +334,7 @@ MessageFormatParser.prototype.ruleInInterpolationOrMessageText = function ruleIn this.ruleStack.push(this.ruleEndMustacheInInterpolationOrMessage); this.rule = this.ruleEnteredMustache; } else if (token == "}") { - this.choices[this.choiceKey] = this.interpolationParts.toParsedFn(this.mustHaveExpression, this.text); + this.choices[this.choiceKey] = this.interpolationParts.toParsedFn(/*mustHaveExpression=*/false, this.text); this.rule = this.ruleChoiceKeyword; } else if (token == "#") { this.interpolationParts.addExpressionFn(this.expressionMinusOffsetFn); diff --git a/src/ngMessageFormat/messageFormatService.js b/src/ngMessageFormat/messageFormatService.js index 21c8b2488a77..75148be123f3 100644 --- a/src/ngMessageFormat/messageFormatService.js +++ b/src/ngMessageFormat/messageFormatService.js @@ -17,6 +17,58 @@ * Angular internal service to recognize MessageFormat extensions in interpolation expressions. * For more information, see: * https://docs.google.com/a/google.com/document/d/1pbtW2yvtmFBikfRrJd8VAsabiFkKezmYZ_PbgdjQOVU/edit + * + * ## Example + * + * + * + *
    + *
    + * {{recipients.length, plural, offset:1 + * =0 {{{sender.name}} gave no gifts (\#=#)} + * =1 {{{sender.name}} gave one gift to {{recipients[0].name}} (\#=#)} + * one {{{sender.name}} gave {{recipients[0].name}} and one other person a gift (\#=#)} + * other {{{sender.name}} gave {{recipients[0].name}} and # other people a gift (\#=#)} + * }} + *
    + *
    + * + * + * function Person(name, gender) { + * this.name = name; + * this.gender = gender; + * } + * + * var alice = new Person("Alice", "female"), + * bob = new Person("Bob", "male"), + * charlie = new Person("Charlie", "male"), + * harry = new Person("Harry Potter", "male"); + * + * angular.module('msgFmtExample', ['ngMessageFormat']) + * .controller('AppController', ['$scope', function($scope) { + * $scope.recipients = [alice, bob, charlie]; + * $scope.sender = harry; + * $scope.decreaseRecipients = function() { + * --$scope.recipients.length; + * }; + * }]); + * + * + * + * describe('MessageFormat plural', function() { + * it('should pluralize initial values', function() { + * var messageElem = element(by.id('message')), decreaseRecipientsBtn = element(by.id('decreaseRecipients')); + * expect(messageElem.getText()).toEqual('Harry Potter gave Alice and 2 other people a gift (#=2)'); + * decreaseRecipientsBtn.click(); + * expect(messageElem.getText()).toEqual('Harry Potter gave Alice and one other person a gift (#=1)'); + * decreaseRecipientsBtn.click(); + * expect(messageElem.getText()).toEqual('Harry Potter gave one gift to Alice (#=0)'); + * decreaseRecipientsBtn.click(); + * expect(messageElem.getText()).toEqual('Harry Potter gave no gifts (#=-1)'); + * }); + * }); + * + *
    */ var $$MessageFormatFactory = ['$parse', '$locale', '$sce', '$exceptionHandler', function $$messageFormat( $parse, $locale, $sce, $exceptionHandler) { @@ -61,7 +113,7 @@ var $$interpolateDecorator = ['$$messageFormat', '$delegate', function $$interpo * @name ngMessageFormat * @description */ -var module = angular['module']('ngMessageFormat', ['ng']); +var module = window['angular']['module']('ngMessageFormat', ['ng']); module['factory']('$$messageFormat', $$MessageFormatFactory); module['config'](['$provide', function($provide) { $provide['decorator']('$interpolate', $$interpolateDecorator); diff --git a/test/ngMessageFormat/messageFormatSpec.js b/test/ngMessageFormat/messageFormatSpec.js index fefe3b1d05da..86bbc824ad7f 100644 --- a/test/ngMessageFormat/messageFormatSpec.js +++ b/test/ngMessageFormat/messageFormatSpec.js @@ -125,7 +125,7 @@ describe('$$ngMessageFormat', function() { " one {YOU SHOULD NEVER SEE THIS MESSAGE}\n" + " other {You gave some people gifts}\n" + "}}"; - var parsedFn = $interpolate(text); + var parsedFn = $interpolate(text, /*mustHaveExpression=*/true); $rootScope.recipients.length=2; expect(parsedFn($rootScope)).toEqual("You gave some people gifts"); @@ -146,7 +146,7 @@ describe('$$ngMessageFormat', function() { " one {YOU SHOULD NEVER SEE THIS MESSAGE}\n" + " other {{{sender.name}} gave them a gift}\n" + "}}"; - var parsedFn = $interpolate(text); + var parsedFn = $interpolate(text, /*mustHaveExpression=*/true); $rootScope.recipients.length=2; expect(parsedFn($rootScope)).toEqual("Harry Potter gave them a gift"); @@ -167,7 +167,7 @@ describe('$$ngMessageFormat', function() { " one {{{sender.name}} gave {{recipients[0].name}} and one other person a gift (\\#=#)}\n" + " other {{{sender.name}} gave {{recipients[0].name}} and # other people a gift (\\#=#)}\n" + "}}"; - var parsedFn = $interpolate(text); + var parsedFn = $interpolate(text, /*mustHaveExpression=*/true); $rootScope.recipients.length=3; // "#" should get replaced with the value of "recipients.length - offset" @@ -196,7 +196,7 @@ describe('$$ngMessageFormat', function() { " }\n" + " other {You gave {{recipients.length}} people gifts. -{{sender.name}}}\n" + "}}"; - var parsedFn = $interpolate(text); + var parsedFn = $interpolate(text, /*mustHaveExpression=*/true); var result = parsedFn($rootScope); expect(result).toEqual("You gave 3 people gifts. -Harry Potter"); }); From 89a57ef842b511a9a3c581a33b4fcb0f060181f7 Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Wed, 15 Apr 2015 16:48:08 +0300 Subject: [PATCH 197/489] docs($http): minor fixes regarding params serializers Closes #11601 --- src/ng/http.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ng/http.js b/src/ng/http.js index e4910219ff51..1b295f9908b7 100644 --- a/src/ng/http.js +++ b/src/ng/http.js @@ -61,7 +61,7 @@ function $HttpParamSerializerJQLikeProvider() { * @name $httpParamSerializerJQLike * @description * - * Alternative $http params serializer that follows jQuerys `param()` method {http://api.jquery.com/jquery.param/} logic. + * Alternative $http params serializer that follows jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic. * */ this.$get = function() { return paramSerializerFactory(true); @@ -214,8 +214,8 @@ function $HttpProvider() { * * - **`defaults.paramSerializer`** - {string|function(Object):string} - A function used to prepare string representation * of request parameters (specified as an object). - * Is specified as string, it is interpreted as function registered in with the {$injector}. - * Defaults to {$httpParamSerializer}. + * If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}. + * Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}. * **/ var defaults = this.defaults = { From b105a7785e68add56a4e69b6a4324f12462aabd1 Mon Sep 17 00:00:00 2001 From: Chirayu Krishnappa Date: Tue, 14 Apr 2015 18:10:13 -0700 Subject: [PATCH 198/489] chore(ngMessageFormat): rename angular-messageFormat to angular-message-format Closes #11595 Closes #11597 --- Gruntfile.js | 4 ++-- docs/content/error/$interpolate/logicbug.ngdoc | 2 +- docs/content/error/$interpolate/nochgmustache.ngdoc | 2 +- docs/content/guide/i18n.ngdoc | 4 ++-- lib/grunt/utils.js | 2 +- src/ngMessageFormat/messageFormatService.js | 5 +++-- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 1e77eba3d8f3..b4c111e22d22 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -204,7 +204,7 @@ module.exports = function(grunt) { src: util.wrap(files['angularModules']['ngResource'], 'module') }, messageformat: { - dest: 'build/angular-messageFormat.js', + dest: 'build/angular-message-format.js', src: util.wrap(files['angularModules']['ngMessageFormat'], 'module') }, messages: { @@ -239,7 +239,7 @@ module.exports = function(grunt) { animate: 'build/angular-animate.js', cookies: 'build/angular-cookies.js', loader: 'build/angular-loader.js', - messageformat: 'build/angular-messageFormat.js', + messageformat: 'build/angular-message-format.js', messages: 'build/angular-messages.js', touch: 'build/angular-touch.js', resource: 'build/angular-resource.js', diff --git a/docs/content/error/$interpolate/logicbug.ngdoc b/docs/content/error/$interpolate/logicbug.ngdoc index c06d36468911..c660d8d39706 100644 --- a/docs/content/error/$interpolate/logicbug.ngdoc +++ b/docs/content/error/$interpolate/logicbug.ngdoc @@ -3,7 +3,7 @@ @fullName Bug in ngMessageFormat module @description -You've just hit a bug in the ngMessageFormat module provided by angular-messageFormat.min.js. +You've just hit a bug in the ngMessageFormat module provided by angular-message-format.min.js. Please file a github issue for this and provide the interpolation text that caused you to hit this bug mentioning the exact version of AngularJS used and we will fix it! diff --git a/docs/content/error/$interpolate/nochgmustache.ngdoc b/docs/content/error/$interpolate/nochgmustache.ngdoc index df590dca92aa..01652dafef02 100644 --- a/docs/content/error/$interpolate/nochgmustache.ngdoc +++ b/docs/content/error/$interpolate/nochgmustache.ngdoc @@ -4,7 +4,7 @@ @description You have redefined `$interpolate.startSymbol`/`$interpolate.endSymbol` and also -loaded the `ngMessageFormat` module (provided by angular-messageFormat.min.js) +loaded the `ngMessageFormat` module (provided by angular-message-format.min.js) while creating your injector. `ngMessageFormat` currently does not support redefinition of the diff --git a/docs/content/guide/i18n.ngdoc b/docs/content/guide/i18n.ngdoc index c1953260e106..689a28baac98 100644 --- a/docs/content/guide/i18n.ngdoc +++ b/docs/content/guide/i18n.ngdoc @@ -154,8 +154,8 @@ You can read more about the ICU MessageFormat syntax at This extended syntax is provided by way of the `ngMessageFormat` module that your application can depend -upon (shipped separately as `angular-messageFormat.min.js` and -`angular-messageFormat.js`.) A current limitation of the +upon (shipped separately as `angular-message-format.min.js` and +`angular-message-format.js`.) A current limitation of the `ngMessageFormat` module, is that it does not support redefining the `$interpolate` start and end symbols. Only the default `{{` and `}}` are allowed. diff --git a/lib/grunt/utils.js b/lib/grunt/utils.js index 80c97750a284..71fc5441fd80 100644 --- a/lib/grunt/utils.js +++ b/lib/grunt/utils.js @@ -185,7 +185,7 @@ module.exports = { var mapFileName = mapFile.match(/[^\/]+$/)[0]; var errorFileName = file.replace(/\.js$/, '-errors.json'); var versionNumber = grunt.config('NG_VERSION').full; - var compilationLevel = (file === 'build/angular-messageFormat.js') ? + var compilationLevel = (file === 'build/angular-message-format.js') ? 'ADVANCED_OPTIMIZATIONS' : 'SIMPLE_OPTIMIZATIONS'; shell.exec( 'java ' + diff --git a/src/ngMessageFormat/messageFormatService.js b/src/ngMessageFormat/messageFormatService.js index 75148be123f3..6f3abfc0f892 100644 --- a/src/ngMessageFormat/messageFormatService.js +++ b/src/ngMessageFormat/messageFormatService.js @@ -20,7 +20,7 @@ * * ## Example * - * + * * *
    *
    @@ -99,7 +99,7 @@ var $$MessageFormatFactory = ['$parse', '$locale', '$sce', '$exceptionHandler', var $$interpolateDecorator = ['$$messageFormat', '$delegate', function $$interpolateDecorator($$messageFormat, $interpolate) { if ($interpolate['startSymbol']() != "{{" || $interpolate['endSymbol']() != "}}") { - throw $interpolateMinErr('nochgmustache', 'angular-messageformat.js currently does not allow you to use custom start and end symbols for interpolation.'); + throw $interpolateMinErr('nochgmustache', 'angular-message-format.js currently does not allow you to use custom start and end symbols for interpolation.'); } var interpolate = $$messageFormat['interpolate']; interpolate['startSymbol'] = $interpolate['startSymbol']; @@ -111,6 +111,7 @@ var $$interpolateDecorator = ['$$messageFormat', '$delegate', function $$interpo /** * @ngdoc module * @name ngMessageFormat + * @packageName angular-message-format * @description */ var module = window['angular']['module']('ngMessageFormat', ['ng']); From 063025b66b54b025b9f64f65c71dfc1916dfbb76 Mon Sep 17 00:00:00 2001 From: Chirayu Krishnappa Date: Wed, 15 Apr 2015 13:11:28 -0700 Subject: [PATCH 199/489] docs(i18n): expand the MessageFormat syntax documentation Closes #11576 --- docs/content/guide/i18n.ngdoc | 257 +++++++++++++++++++++++++--------- 1 file changed, 193 insertions(+), 64 deletions(-) diff --git a/docs/content/guide/i18n.ngdoc b/docs/content/guide/i18n.ngdoc index 689a28baac98..b4e96e07064c 100644 --- a/docs/content/guide/i18n.ngdoc +++ b/docs/content/guide/i18n.ngdoc @@ -18,8 +18,10 @@ application means providing translations and localized formats for the abstracte Angular supports i18n/l10n for {@link ng.filter:date date}, {@link ng.filter:number number} and {@link ng.filter:currency currency} filters. -Additionally, Angular supports localizable pluralization support through the {@link -ng.directive:ngPluralize `ngPluralize` directive}. +Localizable pluralization is supported via the {@link ng.directive:ngPluralize `ngPluralize` +directive}. Additionally, you can use MessageFormat extensions to +`$interpolate` for localizable pluralization and gender support in all interpolations via the +`ngMessageFormat` module. All localizable Angular components depend on locale-specific rule sets managed by the {@link ng.$locale `$locale` service}. @@ -142,96 +144,200 @@ displaying the date with a timezone specified by the developer. ## MessageFormat extensions -AngularJS interpolations via `$interpolate` and in templates -support an extended syntax based on a subset of the ICU -MessageFormat that covers plurals and gender selections. +You can write localizable plural and gender based messages in Angular interpolation expressions and +`$interpolate` calls. + +This syntax extension is provided by way of the `ngMessageFormat` module that your application can +depend upon (shipped separately as `angular-message-format.min.js` and `angular-message-format.js`.) +A current limitation of the `ngMessageFormat` module, is that it does not support redefining the +`$interpolate` start and end symbols. Only the default `{{` and `}}` are allowed. + +The syntax extension is based on a subset of the ICU MessageFormat syntax that covers plurals and +gender selections. Please refer to the links in the “Further Reading” section at the bottom of this +section. + +You may find it helpful to play with our [Plnkr Example](http://plnkr.co/edit/QBVRQ70dvKZDWmHW9RyR?p=preview) +as you read the examples below. + +### Plural Syntax + +The syntax for plural based message selection looks like the following: + +```text +{{NUMERIC_EXPRESSION, plural, + =0 {MESSAGE_WHEN_VALUE_IS_0} + =1 {MESSAGE_WHEN_VALUE_IS_1} + =2 {MESSAGE_WHEN_VALUE_IS_2} + =3 {MESSAGE_WHEN_VALUE_IS_3} + ... + zero {MESSAGE_WHEN_PLURAL_CATEGORY_IS_ZERO} + one {MESSAGE_WHEN_PLURAL_CATEGORY_IS_ONE} + two {MESSAGE_WHEN_PLURAL_CATEGORY_IS_TWO} + few {MESSAGE_WHEN_PLURAL_CATEGORY_IS_FEW} + many {MESSAGE_WHEN_PLURAL_CATEGORY_IS_MANY} + other {MESSAGE_WHEN_THERE_IS_NO_MATCH} +}} +``` -Please refer to our [design doc](https://docs.google.com/a/google.com/document/d/1pbtW2yvtmFBikfRrJd8VAsabiFkKezmYZ_PbgdjQOVU/edit) -for a lot more details. You may find it helpful to play with our [Plnkr Example](http://plnkr.co/edit/QBVRQ70dvKZDWmHW9RyR?p=preview). +Please note that whitespace (including newline) is generally insignificant except as part of the +actual message text that occurs in curly braces. Whitespace is generally used to aid readability. -You can read more about the ICU MessageFormat syntax at -[Formatting Messages | ICU User Guide](http://userguide.icu-project.org/formatparse/messages#TOC-MessageFormat). +Here, `NUMERIC_EXPRESSION` is an expression that evaluates to a numeric value based on which the +displayed message should change based on pluralization rules. + +Following the Angular expression, you would denote the plural extension syntax by the `, plural,` +syntax element. The spaces there are optional. + +This is followed by a list of selection keyword and corresponding message pairs. The "other" +keyword and corresponding message are **required** but you may have as few or as many of the other +categories as you need. + +#### Selection Keywords + +The selection keywords can be either exact matches or language dependent [plural +categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html). + +Exact matches are written as the equal sign followed by the exact value. `=0`, `=1`, `=2` and +`=123` are all examples of exact matches. Note that there should be no space between the equal sign +and the numeric value. + +Plural category matches are single words corresponding to the [plural +categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html) of +the CLDR plural category spec. These categories vary by locale. The "en" (English) locale, for +example, defines just "one" and "other" while the "ga" (Irish) locale defines "one", "two", "few", +"many" and "other". Typically, you would just write the categories for your language. During +translation, the translators will add or remove more categories depending on the target locale. + +Exact matches always win over keyword matches. Therefore, if you define both `=0` and `zero`, when +the value of the expression is zero, the `=0` message is the one that will be selected. (The +duplicate keyword categories are helpful when used with the optional `offset` syntax described +later.) -This extended syntax is provided by way of the -`ngMessageFormat` module that your application can depend -upon (shipped separately as `angular-message-format.min.js` and -`angular-message-format.js`.) A current limitation of the -`ngMessageFormat` module, is that it does not support -redefining the `$interpolate` start and end symbols. Only the -default `{{` and `}}` are allowed. - -This syntax extension, while based on MessageFormat, has -been designed to be backwards compatible with existing -AngularJS interpolation expressions. The key rule is simply -this: **All interpolations are done inside double curlies.** -The top level comma operator after an expression inside the -double curlies causes MessageFormat extensions to be -recognized. Such a top level comma is otherwise illegal in -an Angular expression and is used by MessageFormat to -specify the function (such as plural/select) and it's -related syntax. - -To understand the extension, take a look at the ICU -MessageFormat syntax as specified by the ICU documentation. -Anywhere in that MessageFormat that you have regular message -text and you want to substitute an expression, just put it -in double curlies instead of single curlies that -MessageFormat dictates. This has a huge advantage. **You -are no longer limited to simple identifiers for -substitutions**. Because you are using double curlies, you -can stick in any arbitrary interpolation syntax there, -including nesting more MessageFormat expressions! Some -examples will make this clear. In the following example, I -will only be showing you the AngularJS syntax. +#### Messages + +Messages immediately follow a selection keyword and are optionally preceded by whitespace. They are +written in single curly braces (`{}`). They may contain Angular interpolation syntax inside them. +In addition, the `#` symbol is a placeholder for the actual numeric value of the expression. ### Simple plural example -``` +```text {{numMessages, plural, - =0 { You have no new messages } - =1 { You have one new message } - other { You have # new messages } + =0 {You have no new messages} + =1 {You have one new message} + other {You have # new messages} }} ``` -While I won't be teaching you MessageFormat here, you will -note that the `#` symbol works as expected. You could have -also written it as: +Because these messages can themselves contain Angular expressions, you could also write this as +follows: -``` +```text {{numMessages, plural, - =0 { You have no new messages } - =1 { You have one new message } - other { You have {{numMessages}} new messages } + =0 {You have no new messages} + =1 {You have one new message} + other {You have {{numMessages}} new messages} }} ``` -where you explicitly typed in `numMessages` for "other" -instead of using `#`. They are nearly the same except if -you're using "offset". Refer to the ICU MessageFormat -documentation to learn about offset. -Please note that **other** is a **required** category (for -both the plural syntax and the select syntax that is shown -later.) +### Plural syntax with optional `offset` + +The plural syntax supports an optional `offset` syntax that is used in matching. It's simpler to +explain this with an example. + +```text +{{recipients.length, plural, offset:1 + =0 {You gave no gifts} + =1 {You gave {{recipients[0].name}} a gift} + one {You gave {{recipients[0].name}} and one other person a gift} + other {You gave {{recipients[0].name}} and # other people a gift} +}} +``` + +When an `offset` is specified, the matching works as follows. First, the exact value of the Angular +expression is matched against the exact matches (i.e. `=N` selectors) to find a match. If there is +one, that message is used. If there was no match, then the offset value is subtracted from the +value of the expression and locale specific pluralization rules are applied to this new value to +obtain its plural category (such as “one”, “few”, “many”, etc.) and a match is attempted against the +keyword selectors and the matching message is used. If there was no match, then the “other” +category (required) is used. The value of the `#` character inside a message is the value of +original expression reduced by the offset value that was specified. + +### Escaping / Quoting + +You will need to escape curly braces or the `#` character inside message texts if you want them to +be treated literally with no special meaning. You may quote/escape any character in your message +text by preceding it with a `\` (backslash) character. The backslash character removes any special +meaning to the character that immediately follows it. Therefore, you can escape or quote the +backslash itself by preceding it with another backslash character. -### Simple select (for gender) example +### Gender (aka select) Syntax +The gender support is provided by the more generic "select" syntax that is more akin to a switch +statement. It is general enough to support use for gender based messages. + +The syntax for gender based message selection looks like the following: + +```text +{{EXPRESSION, select, + male {MESSAGE_WHEN_EXPRESSION_IS_MALE} + female {MESSAGE_WHEN_EXPRESSION_IS_FEMALE} + ... + other {MESSAGE_WHEN_THERE_IS_NO_GENDER_MATCH} +}} ``` + +Please note that whitespace (including newline) is generally insignificant except as part of the +actual message text that occurs in curly braces. Whitespace is generally used to aid readability. + +Here, `EXPRESSION` is an Angular expression that evaluates to the gender of the person that +is used to select the message that should be displayed. + +The Angular expression is followed by `, select,` where the spaces are optional. + +This is followed by a list of selection keyword and corresponding message pairs. The "other" +keyword and corresponding message are **required** but you may have as few or as many of the other +gender values as you need (i.e. it isn't restricted to male/female.) Note however, that the +matching is **case-sensitive**. + +#### Selection Keywords + +Selection keywords are simple words like "male" and "female". The keyword, "other", and it's +corresponding message are required while others are optional. It is used when the Angular +expression does not match (case-insensitively) any of the other keywords specified. + +#### Messages + +Messages immediately follow a selection keyword and are optionally preceded by whitespace. They are +written in single curly braces (`{}`). They may contain Angular interpolation syntax inside them. + +### Simple gender example + +```text {{friendGender, select, - male { Invite him } - female { Invite her } - other { Invite them } + male {Invite him} + female {Invite her} + other {Invite them} }} ``` -### More complex example that combines some of these +### Nesting + +As mentioned in the syntax for plural and select, the embedded messages can contain Angular +interpolation syntax. Since you can use MessageFormat extensions in Angular interpolation, this +allows you to nest plural and gender expressions in any order. + +Please note that if these are intended to reach a translator and be translated, it is recommended +that the messages appear as a whole and not be split up. + +### More complex example that demonstrates nesting This is taken from the [plunker example](http://plnkr.co/edit/QBVRQ70dvKZDWmHW9RyR?p=preview) linked to earlier. -``` +```text {{recipients.length, plural, offset:1 =0 {You ({{sender.name}}) gave no gifts} =1 { {{ recipients[0].gender, select, @@ -249,3 +355,26 @@ This is taken from the [plunker example](http://plnkr.co/edit/QBVRQ70dvKZDWmHW9R other {You ({{sender.name}}) gave {{recipients.length}} people gifts. } }} ``` + +### Differences from the ICU MessageFormat syntax + +This section is useful to you if you're already familiar with the ICU MessageFormat syntax. + +This syntax extension, while based on MessageFormat, has been designed to be backwards compatible +with existing AngularJS interpolation expressions. The key rule is simply this: **All +interpolations are done inside double curlies.** The top level comma operator after an expression +inside the double curlies causes MessageFormat extensions to be recognized. Such a top level comma +is otherwise illegal in an Angular expression and is used by MessageFormat to specify the function +(such as plural/select) and it's related syntax. + +To understand the extension, take a look at the ICU MessageFormat syntax as specified by the ICU +documentation. Anywhere in that MessageFormat that you have regular message text and you want to +substitute an expression, just put it in double curlies instead of single curlies that MessageFormat +dictates. This has a huge advantage. **You are no longer limited to simple identifiers for +substitutions**. Because you are using double curlies, you can stick in any arbitrary interpolation +syntax there, including nesting more MessageFormat expressions! + +### Further Reading +For more details, please refer to our [design doc](https://docs.google.com/a/google.com/document/d/1pbtW2yvtmFBikfRrJd8VAsabiFkKezmYZ_PbgdjQOVU/edit). +You can read more about the ICU MessageFormat syntax at +[Formatting Messages | ICU User Guide](http://userguide.icu-project.org/formatparse/messages#TOC-MessageFormat). From efa55826895a7a7b66b4e44ba92725926bf11a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Mon, 13 Apr 2015 22:19:53 -0700 Subject: [PATCH 200/489] fix(ngAnimate): ensure that animations work when the app is bootstrapped on the document node Closes #11574 --- src/ngAnimate/animateQueue.js | 12 ++++++------ test/ngAnimate/animateSpec.js | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/ngAnimate/animateQueue.js b/src/ngAnimate/animateQueue.js index 3d5b58f27fc5..a536a55cbb5e 100644 --- a/src/ngAnimate/animateQueue.js +++ b/src/ngAnimate/animateQueue.js @@ -491,6 +491,12 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { var animateChildren; while (parent && parent.length) { + if (!rootElementDetected) { + // angular doesn't want to attempt to animate elements outside of the application + // therefore we need to ensure that the rootElement is an ancestor of the current element + rootElementDetected = isMatchingElement(parent, $rootElement); + } + var parentNode = parent[0]; if (parentNode.nodeType !== ELEMENT_NODE) { // no point in inspecting the #document element @@ -515,12 +521,6 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { // there is no need to continue traversing at this point if (parentAnimationDetected && animateChildren === false) break; - if (!rootElementDetected) { - // angular doesn't want to attempt to animate elements outside of the application - // therefore we need to ensure that the rootElement is an ancestor of the current element - rootElementDetected = isMatchingElement(parent, $rootElement); - } - if (!bodyElementDetected) { // we also need to ensure that the element is or will be apart of the body element // otherwise it is pointless to even issue an animation to be rendered diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index 5d89274585c4..5ac1b6053073 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -10,6 +10,33 @@ describe("animations", function() { dealoc(element); })); + it('should allow animations if the application is bootstrapped on the document node', function() { + var capturedAnimation; + + module(function($provide) { + $provide.factory('$rootElement', function($document) { + return $document; + }); + $provide.factory('$$animation', function($$AnimateRunner) { + return function() { + capturedAnimation = arguments; + return new $$AnimateRunner(); + }; + }); + }); + + inject(function($animate, $rootScope, $document) { + $animate.enabled(true); + + element = jqLite('
    '); + + $animate.enter(element, jqLite($document[0].body)); + $rootScope.$digest(); + + expect(capturedAnimation).toBeTruthy(); + }); + }); + describe('during bootstrap', function() { it('should be enabled only after the first digest is fired and the postDigest queue is empty', inject(function($animate, $rootScope) { From cfb5884c879462892fda6140c6864ab60f3872a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Mon, 13 Apr 2015 20:21:59 -0700 Subject: [PATCH 201/489] test(ngAnimate): add basic integration tests for JS/CSS $animate-based animations --- test/ngAnimate/integrationSpec.js | 190 ++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 test/ngAnimate/integrationSpec.js diff --git a/test/ngAnimate/integrationSpec.js b/test/ngAnimate/integrationSpec.js new file mode 100644 index 000000000000..5e01abc25800 --- /dev/null +++ b/test/ngAnimate/integrationSpec.js @@ -0,0 +1,190 @@ +'use strict'; + +describe('ngAnimate integration tests', function() { + + beforeEach(module('ngAnimate')); + + var html, ss; + beforeEach(module(function() { + return function($rootElement, $document, $window, $animate) { + $animate.enabled(true); + + ss = createMockStyleSheet($document, $window); + + var body = jqLite($document[0].body); + html = function(element) { + body.append($rootElement); + $rootElement.append(element); + }; + }; + })); + + describe('CSS animations', function() { + if (!browserSupportsCssAnimations()) return; + + they('should render an $prop animation', + ['enter', 'leave', 'move', 'addClass', 'removeClass', 'setClass'], function(event) { + + inject(function($animate, $compile, $rootScope, $rootElement, $$rAF) { + var element = jqLite('
    '); + $compile(element)($rootScope); + + var className = 'klass'; + var addClass, removeClass; + var parent = jqLite('
    '); + html(parent); + + var setupClass, activeClass; + var args; + var classRuleSuffix = ''; + + switch (event) { + case 'enter': + case 'move': + setupClass = 'ng-' + event; + activeClass = 'ng-' + event + '-active'; + args = [element, parent]; + break; + + case 'leave': + parent.append(element); + setupClass = 'ng-' + event; + activeClass = 'ng-' + event + '-active'; + args = [element]; + break; + + case 'addClass': + parent.append(element); + classRuleSuffix = '.add'; + setupClass = className + '-add'; + activeClass = className + '-add-active'; + addClass = className; + args = [element, className]; + break; + + case 'removeClass': + parent.append(element); + setupClass = className + '-remove'; + activeClass = className + '-remove-active'; + element.addClass(className); + args = [element, className]; + break; + + case 'setClass': + parent.append(element); + addClass = className; + removeClass = 'removing-class'; + setupClass = addClass + '-add ' + removeClass + '-remove'; + activeClass = addClass + '-add-active ' + removeClass + '-remove-active'; + element.addClass(removeClass); + args = [element, addClass, removeClass]; + break; + } + + ss.addRule('.animate-me', 'transition:2s linear all;'); + + var runner = $animate[event].apply($animate, args); + $rootScope.$digest(); + + var animationCompleted = false; + runner.then(function() { + animationCompleted = true; + }); + + expect(element).toHaveClass(setupClass); + $$rAF.flush(); + expect(element).toHaveClass(activeClass); + + browserTrigger(element, 'transitionend', { timeStamp: Date.now(), elapsedTime: 2 }); + + expect(element).not.toHaveClass(setupClass); + expect(element).not.toHaveClass(activeClass); + + $rootScope.$digest(); + + expect(animationCompleted).toBe(true); + }); + }); + }); + + describe('JS animations', function() { + they('should render an $prop animation', + ['enter', 'leave', 'move', 'addClass', 'removeClass', 'setClass'], function(event) { + + var endAnimation; + var animateCompleteCallbackFired = true; + + module(function($animateProvider) { + $animateProvider.register('.animate-me', function() { + var animateFactory = {}; + animateFactory[event] = function(element, addClass, removeClass, done) { + endAnimation = arguments[arguments.length - 2]; // the done method is the 2nd last one + return function(status) { + animateCompleteCallbackFired = status === false; + }; + }; + return animateFactory; + }); + }); + + inject(function($animate, $compile, $rootScope, $rootElement, $$rAF) { + var element = jqLite('
    '); + $compile(element)($rootScope); + + var className = 'klass'; + var addClass, removeClass; + var parent = jqLite('
    '); + html(parent); + + var args; + switch (event) { + case 'enter': + case 'move': + args = [element, parent]; + break; + + case 'leave': + parent.append(element); + args = [element]; + break; + + case 'addClass': + parent.append(element); + args = [element, className]; + break; + + case 'removeClass': + parent.append(element); + element.addClass(className); + args = [element, className]; + break; + + case 'setClass': + parent.append(element); + addClass = className; + removeClass = 'removing-class'; + element.addClass(removeClass); + args = [element, addClass, removeClass]; + break; + } + + var runner = $animate[event].apply($animate, args); + var animationCompleted = false; + runner.then(function() { + animationCompleted = true; + }); + + $rootScope.$digest(); + + expect(isFunction(endAnimation)).toBe(true); + + endAnimation(); + $$rAF.flush(); + expect(animateCompleteCallbackFired).toBe(true); + + $rootScope.$digest(); + expect(animationCompleted).toBe(true); + }); + }); + }); +}); From e0d1eb8d407709de06ee0df98e4689a4b9026624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Mon, 13 Apr 2015 17:53:18 -0700 Subject: [PATCH 202/489] fix(ngAnimate): ensure that a filtered-out leave animation always runs its DOM operation This patch fixes the issue where filtered-out leave animations were not properly run the DOM operation when closed. Closes #11555 --- src/ngAnimate/animateQueue.js | 2 +- test/ngAnimate/animateSpec.js | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/ngAnimate/animateQueue.js b/src/ngAnimate/animateQueue.js index a536a55cbb5e..72c67b068ec8 100644 --- a/src/ngAnimate/animateQueue.js +++ b/src/ngAnimate/animateQueue.js @@ -250,7 +250,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { var className = [node.className, options.addClass, options.removeClass].join(' '); if (!isAnimatableClassName(className)) { - runner.end(); + close(); return runner; } diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index 5ac1b6053073..d162b079e58d 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -133,7 +133,7 @@ describe("animations", function() { module(function($animateProvider) { $animateProvider.classNameFilter(/only-allow-this-animation/); }); - inject(function($animate, $rootScope, $document, $rootElement) { + inject(function($animate, $rootScope) { expect(element).not.toHaveClass('only-allow-this-animation'); $animate.enter(element, parent); @@ -148,6 +148,22 @@ describe("animations", function() { }); }); + it('should complete the leave DOM operation in case the classNameFilter fails', function() { + module(function($animateProvider) { + $animateProvider.classNameFilter(/memorable-animation/); + }); + inject(function($animate, $rootScope) { + expect(element).not.toHaveClass('memorable-animation'); + + parent.append(element); + $animate.leave(element); + $rootScope.$digest(); + + expect(capturedAnimation).toBeFalsy(); + expect(element[0].parentNode).toBeFalsy(); + }); + }); + describe('enabled()', function() { it("should work for all animations", inject(function($animate) { From 0b59adb8991617be2292233cbe67497ee768de8c Mon Sep 17 00:00:00 2001 From: Chirayu Krishnappa Date: Wed, 15 Apr 2015 13:36:46 -0700 Subject: [PATCH 203/489] chore(bower): minor refactor to DRY The REPOS list was duplicated in publish.sh and unpublish.sh but had different orderings of the repos. This commit consolidates the list into a common include file so that they are always in sync. We could improve the scripts a lot more but that's not in the current scope (this is all I need to scratch my current itch.) Closes #11605 --- scripts/bower/publish.sh | 16 +--------------- scripts/bower/repos.inc | 19 +++++++++++++++++++ scripts/bower/unpublish.sh | 16 +--------------- 3 files changed, 21 insertions(+), 30 deletions(-) create mode 100644 scripts/bower/repos.inc diff --git a/scripts/bower/publish.sh b/scripts/bower/publish.sh index e89f1ced0228..c7af4ccc4c86 100755 --- a/scripts/bower/publish.sh +++ b/scripts/bower/publish.sh @@ -14,21 +14,7 @@ function init { TMP_DIR=$(resolveDir ../../tmp) BUILD_DIR=$(resolveDir ../../build) NEW_VERSION=$(cat $BUILD_DIR/version.txt) - REPOS=( - angular - angular-animate - angular-aria - angular-cookies - angular-i18n - angular-loader - angular-mocks - angular-route - angular-resource - angular-sanitize - angular-scenario - angular-touch - angular-messages - ) + source $(dirname $0)/repos.inc } diff --git a/scripts/bower/repos.inc b/scripts/bower/repos.inc new file mode 100644 index 000000000000..b2b1421be1b4 --- /dev/null +++ b/scripts/bower/repos.inc @@ -0,0 +1,19 @@ +#!/bin/false +# -*- mode: sh; -*- vim: set filetype=sh: + +REPOS=( + angular + angular-animate + angular-aria + angular-cookies + angular-i18n + angular-loader + angular-message-format + angular-messages + angular-mocks + angular-resource + angular-route + angular-sanitize + angular-scenario + angular-touch +) diff --git a/scripts/bower/unpublish.sh b/scripts/bower/unpublish.sh index 683ac1cbd3be..8b415e625b67 100755 --- a/scripts/bower/unpublish.sh +++ b/scripts/bower/unpublish.sh @@ -13,21 +13,7 @@ ARG_DEFS=( function init { TMP_DIR=$(resolveDir ../../tmp) - REPOS=( - angular - angular-animate - angular-aria - angular-cookies - angular-i18n - angular-loader - angular-messages - angular-mocks - angular-route - angular-resource - angular-sanitize - angular-scenario - angular-touch - ) + source $(dirname $0)/repos.inc } function prepare { From 72952b77aaf444d616949453fb2741c2f7d50915 Mon Sep 17 00:00:00 2001 From: Chirayu Krishnappa Date: Wed, 15 Apr 2015 15:49:52 -0700 Subject: [PATCH 204/489] chore(bower): (un)publish angular-message-format Closes #11606 Closes #11607 --- scripts/bower/publish.sh | 2 +- scripts/bower/unpublish.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/bower/publish.sh b/scripts/bower/publish.sh index c7af4ccc4c86..5189206f4384 100755 --- a/scripts/bower/publish.sh +++ b/scripts/bower/publish.sh @@ -14,7 +14,6 @@ function init { TMP_DIR=$(resolveDir ../../tmp) BUILD_DIR=$(resolveDir ../../build) NEW_VERSION=$(cat $BUILD_DIR/version.txt) - source $(dirname $0)/repos.inc } @@ -115,4 +114,5 @@ function publish { done } +source $(dirname $0)/repos.inc source $(dirname $0)/../utils.inc diff --git a/scripts/bower/unpublish.sh b/scripts/bower/unpublish.sh index 8b415e625b67..f05a5d1699a2 100755 --- a/scripts/bower/unpublish.sh +++ b/scripts/bower/unpublish.sh @@ -13,7 +13,6 @@ ARG_DEFS=( function init { TMP_DIR=$(resolveDir ../../tmp) - source $(dirname $0)/repos.inc } function prepare { @@ -39,4 +38,5 @@ function publish { done } +source $(dirname $0)/repos.inc source $(dirname $0)/../utils.inc From f20263f58963db71890a9dcc192a7dd905cb6aed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Sun, 12 Apr 2015 19:25:03 -0700 Subject: [PATCH 205/489] fix(ngAnimate): do not abort animation if only `ng-anchor-in` is used --- src/ngAnimate/animateCssDriver.js | 36 +++++++++++------ test/ngAnimate/animateCssDriverSpec.js | 53 ++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 12 deletions(-) diff --git a/src/ngAnimate/animateCssDriver.js b/src/ngAnimate/animateCssDriver.js index f0e2fdace984..92baa08ecfc7 100644 --- a/src/ngAnimate/animateCssDriver.js +++ b/src/ngAnimate/animateCssDriver.js @@ -56,27 +56,39 @@ var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationPro rootBodyElement.append(clone); - var animatorOut = prepareOutAnimation(); + var animatorIn, animatorOut = prepareOutAnimation(); + + // the user may not end up using the `out` animation and + // only making use of the `in` animation or vice-versa. + // In either case we should allow this and not assume the + // animation is over unless both animations are not used. if (!animatorOut) { - return end(); + animatorIn = prepareInAnimation(); + if (!animatorIn) { + return end(); + } } + var startingAnimator = animatorOut || animatorIn; + return { start: function() { var runner; - var currentAnimation = animatorOut.start(); + var currentAnimation = startingAnimator.start(); currentAnimation.done(function() { currentAnimation = null; - var animatorIn = prepareInAnimation(); - if (animatorIn) { - currentAnimation = animatorIn.start(); - currentAnimation.done(function() { - currentAnimation = null; - end(); - runner.complete(); - }); - return currentAnimation; + if (!animatorIn) { + animatorIn = prepareInAnimation(); + if (animatorIn) { + currentAnimation = animatorIn.start(); + currentAnimation.done(function() { + currentAnimation = null; + end(); + runner.complete(); + }); + return currentAnimation; + } } // in the event that there is no `in` animation end(); diff --git a/test/ngAnimate/animateCssDriverSpec.js b/test/ngAnimate/animateCssDriverSpec.js index 81a9e14cda42..aead475b231c 100644 --- a/test/ngAnimate/animateCssDriverSpec.js +++ b/test/ngAnimate/animateCssDriverSpec.js @@ -410,6 +410,59 @@ describe("ngAnimate $$animateCssDriver", function() { expect(anchorDetails.event).toBeFalsy(); })); + they("should only fire the ng-anchor-$prop animation if only a $prop animation is defined", + ['out', 'in'], function(direction) { + + var expectedClass = 'ng-anchor-' + direction; + var animationStarted; + var runner; + + module(function($provide) { + $provide.factory('$animateCss', function($$AnimateRunner) { + return function(element, options) { + var addClass = (options.addClass || '').trim(); + if (addClass === expectedClass) { + return { + start: function() { + animationStarted = addClass; + return runner = new $$AnimateRunner(); + } + }; + } + }; + }); + }); + + inject(function($rootElement, $$rAF) { + var fromAnchor = jqLite('
    '); + from.append(fromAnchor); + var toAnchor = jqLite('
    '); + to.append(toAnchor); + + $rootElement.append(fromAnchor); + $rootElement.append(toAnchor); + + var complete = false; + + driver({ + from: fromAnimation, + to: toAnimation, + anchors: [{ + 'out': fromAnchor, + 'in': toAnchor + }] + }).start().done(function() { + complete = true; + }); + + expect(animationStarted).toBe(expectedClass); + runner.end(); + $$rAF.flush(); + expect(complete).toBe(true); + }); + }); + + it("should provide an explicit delay setting in the options provided to $animateCss for anchor animations", inject(function($rootElement) { From 1f3b83528b71a7e5023c24a65853297883e50c47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Mon, 13 Apr 2015 14:35:11 -0700 Subject: [PATCH 206/489] fix(ngAnimate): ensure ngClass-based classes are always resolved for CSS-enabled animations --- src/ngAnimate/animateCss.js | 56 ++++++++------------------ src/ngAnimate/animateCssDriver.js | 5 +++ test/ngAnimate/animateCssDriverSpec.js | 8 ++++ test/ngAnimate/animateCssSpec.js | 3 +- 4 files changed, 31 insertions(+), 41 deletions(-) diff --git a/src/ngAnimate/animateCss.js b/src/ngAnimate/animateCss.js index 641f07449287..0d8caa35779d 100644 --- a/src/ngAnimate/animateCss.js +++ b/src/ngAnimate/animateCss.js @@ -221,6 +221,7 @@ * ({@link ngAnimate#css-staggering-animations Click here to learn how CSS-based staggering works in ngAnimate.}) * * `staggerIndex` - The numeric index representing the stagger item (e.g. a value of 5 is equal to the sixth item in the stagger; therefore when a * `stagger` option value of `0.1` is used then there will be a stagger delay of `600ms`) + * `applyClassesEarly` - Whether or not the classes being added or removed will be used when detecting the animation. This is set by `$animate` when enter/leave/move animations are fired to ensure that the CSS classes are resolved in time. (Note that this will prevent any transitions from occuring on the classes being added and removed.) * * @return {null|object} an object with a start method and details about the animation. If no animation is detected then a value of `null` will be returned. * @@ -563,6 +564,17 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) { addRemoveClassName += pendClasses(options.removeClass, '-remove'); } + // there may be a situation where a structural animation is combined together + // with CSS classes that need to resolve before the animation is computed. + // However this means that there is no explicit CSS code to block the animation + // from happening (by setting 0s none in the class name). If this is the case + // we need to apply the classes before the first rAF so we know to continue if + // there actually is a detected transition or keyframe animation + if (options.applyClassesEarly && addRemoveClassName.length) { + applyAnimationClasses(element, options); + addRemoveClassName = ''; + } + var setupClasses = [structuralClassName, addRemoveClassName].join(' ').trim(); var fullClassName = classes + ' ' + setupClasses; var activeClasses = pendClasses(setupClasses, '-active'); @@ -644,10 +656,10 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) { flags.applyTransitionDuration = hasToStyles && ( (flags.hasTransitions && !flags.hasTransitionAll) || (flags.hasAnimations && !flags.hasTransitions)); - flags.applyAnimationDuration = options.duration && flags.hasAnimations; - flags.applyTransitionDelay = truthyTimingValue(options.delay) && (flags.applyTransitionDuration || flags.hasTransitions); - flags.applyAnimationDelay = truthyTimingValue(options.delay) && flags.hasAnimations; - flags.recalculateTimingStyles = addRemoveClassName.length > 0; + flags.applyAnimationDuration = options.duration && flags.hasAnimations; + flags.applyTransitionDelay = truthyTimingValue(options.delay) && (flags.applyTransitionDuration || flags.hasTransitions); + flags.applyAnimationDelay = truthyTimingValue(options.delay) && flags.hasAnimations; + flags.recalculateTimingStyles = addRemoveClassName.length > 0; if (flags.applyTransitionDuration || flags.applyAnimationDuration) { maxDuration = options.duration ? parseFloat(options.duration) : maxDuration; @@ -666,42 +678,6 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) { } } - flags.transitionClassBlock = timings.transitionProperty === 'none' && - timings.transitionDuration === 0; - - // there may be a situation where a structural animation is combined together - // with CSS classes that need to resolve before the animation is computed. - // However this means that there is no explicit CSS code to block the animation - // from happening (by setting 0s none in the class name). If this is the case - // we need to apply the classes before the first rAF so we know to continue if - // there actually is a detected transition or keyframe animation - var applyClassesEarly = maxDuration === 0 - && isStructural - && addRemoveClassName.length > 0 - && !flags.transitionClassBlock; - - // this is an early check to avoid having to do another call to getComputedStyle - // call which is expensive. GCS calls are cached to speed things up. - if (!applyClassesEarly && maxDuration === 0 && !flags.recalculateTimingStyles) { - close(); - return false; - } - - if (applyClassesEarly) { - applyAnimationClasses(element, options); - - // no need to calculate this anymore - flags.recalculateTimingStyles = false; - - fullClassName = node.className + ' ' + setupClasses; - cacheKey = gcsHashFn(node, fullClassName); - - timings = computeTimings(node, fullClassName, cacheKey); - relativeDelay = timings.maxDelay; - maxDelay = Math.max(relativeDelay, 0); - maxDuration = timings.maxDuration; - } - if (maxDuration === 0 && !flags.recalculateTimingStyles) { close(); return false; diff --git a/src/ngAnimate/animateCssDriver.js b/src/ngAnimate/animateCssDriver.js index 92baa08ecfc7..bf9b39abb13e 100644 --- a/src/ngAnimate/animateCssDriver.js +++ b/src/ngAnimate/animateCssDriver.js @@ -214,8 +214,13 @@ var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationPro function prepareRegularAnimation(animationDetails) { var element = animationDetails.element; var options = animationDetails.options || {}; + options.structural = animationDetails.structural; + // structural animations ensure that the CSS classes are always applied + // before the detection starts. + options.applyClassesEarly = options.structural; + // we special case the leave animation since we want to ensure that // the element is removed as soon as the animation is over. Otherwise // a flicker might appear or the element may not be removed at all diff --git a/test/ngAnimate/animateCssDriverSpec.js b/test/ngAnimate/animateCssDriverSpec.js index aead475b231c..ed583c38658f 100644 --- a/test/ngAnimate/animateCssDriverSpec.js +++ b/test/ngAnimate/animateCssDriverSpec.js @@ -95,6 +95,14 @@ describe("ngAnimate $$animateCssDriver", function() { var runner = driver({ element: element }); expect(isFunction(runner.start)).toBeTruthy(); })); + + it("should signal $animateCss to apply the classes early when an event is present", inject(function() { + driver({ element: element, structural: true }); + expect(capturedAnimation[1].applyClassesEarly).toBeTruthy(); + + driver({ element: element }); + expect(capturedAnimation[1].applyClassesEarly).toBeFalsy(); + })); }); describe("anchored animations", function() { diff --git a/test/ngAnimate/animateCssSpec.js b/test/ngAnimate/animateCssSpec.js index b0dce41c7203..a47594297e84 100644 --- a/test/ngAnimate/animateCssSpec.js +++ b/test/ngAnimate/animateCssSpec.js @@ -1456,7 +1456,7 @@ describe("ngAnimate $animateCss", function() { }); }); - they('should force the class-based values to be applied early if no transition/keyframe is detected at all', + they('should force the class-based values to be applied early if no options.applyClassEarly is used as an option', ['enter', 'leave', 'move'], function(event) { inject(function($animateCss, $rootElement, $document) { @@ -1468,6 +1468,7 @@ describe("ngAnimate $animateCss", function() { var runner = $animateCss(element, { addClass: 'blue', + applyClassesEarly: true, removeClass: 'red', event: event, structural: true From 20a875f139600a3aa1cb2cac08e34709663b3d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Mon, 13 Apr 2015 17:20:05 -0700 Subject: [PATCH 207/489] feat($animate): provide support for animations on elements outside of $rootElement Beforehand it was impossible to issue an animation via $animate on an element that is outside the realm of an Angular app. Take for example a dropdown menu where the menu is positioned with absolute positioning... The element will most likely need to be placed by the `` tag, but if the angular application is bootstrapped elsewhere then it cannot be animated. This fix provides support for `$animate.pin()` which allows for an external element to be virtually placed in the DOM structure of a host parent element within the DOM of an angular app. --- src/ng/animate.js | 20 +++++++++++ src/ngAnimate/.jshintrc | 1 + src/ngAnimate/animateQueue.js | 24 +++++++++++++ src/ngAnimate/shared.js | 7 ++++ test/ngAnimate/animateSpec.js | 68 +++++++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+) diff --git a/src/ng/animate.js b/src/ng/animate.js index 449bbc6c34e7..4901dfb15550 100644 --- a/src/ng/animate.js +++ b/src/ng/animate.js @@ -72,6 +72,7 @@ var $$CoreAnimateQueueProvider = function() { enabled: noop, on: noop, off: noop, + pin: noop, push: function(element, event, options, domOperation) { domOperation && domOperation(); @@ -272,6 +273,25 @@ var $AnimateProvider = ['$provide', function($provide) { // be interpreted as null within the sub enabled function on: $$animateQueue.on, off: $$animateQueue.off, + + /** + * @ngdoc method + * @name $animate#pin + * @kind function + * @description Associates the provided element with a host parent element to allow the element to be animated even if it exists + * outside of the DOM structure of the Angular application. By doing so, any animation triggered via `$animate` can be issued on the + * element despite being outside the realm of the application or within another application. Say for example if the application + * was bootstrapped on an element that is somewhere inside of the `` tag, but we wanted to allow for an element to be situated + * as a direct child of `document.body`, then this can be achieved by pinning the element via `$animate.pin(element)`. Keep in mind + * that calling `$animate.pin(element, parentElement)` will not actually insert into the DOM anywhere; it will just create the association. + * + * Note that this feature is only active when the `ngAnimate` module is used. + * + * @param {DOMElement} element the external element that will be pinned + * @param {DOMElement} parentElement the host parent element that will be associated with the external element + */ + pin: $$animateQueue.pin, + enabled: $$animateQueue.enabled, cancel: function(runner) { diff --git a/src/ngAnimate/.jshintrc b/src/ngAnimate/.jshintrc index c6a112ff0f22..ff0fac6abb0b 100644 --- a/src/ngAnimate/.jshintrc +++ b/src/ngAnimate/.jshintrc @@ -22,6 +22,7 @@ "ELEMENT_NODE": false, "NG_ANIMATE_CHILDREN_DATA": false, + "assertArg": false, "isPromiseLike": false, "mergeClasses": false, "mergeAnimationOptions": false, diff --git a/src/ngAnimate/animateQueue.js b/src/ngAnimate/animateQueue.js index 72c67b068ec8..1b914485edba 100644 --- a/src/ngAnimate/animateQueue.js +++ b/src/ngAnimate/animateQueue.js @@ -1,6 +1,7 @@ 'use strict'; var NG_ANIMATE_ATTR_NAME = 'data-ng-animate'; +var NG_ANIMATE_PIN_DATA = '$ngAnimatePin'; var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { var PRE_DIGEST_STATE = 1; var RUNNING_STATE = 2; @@ -167,6 +168,12 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { } }, + pin: function(element, parentElement) { + assertArg(isElement(element), 'element', 'not an element'); + assertArg(isElement(parentElement), 'parentElement', 'not an element'); + element.data(NG_ANIMATE_PIN_DATA, parentElement); + }, + push: function(element, event, options, domOperation) { options = options || {}; options.domOperation = domOperation; @@ -490,6 +497,11 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { var parentAnimationDetected = false; var animateChildren; + var parentHost = element.data(NG_ANIMATE_PIN_DATA); + if (parentHost) { + parent = parentHost; + } + while (parent && parent.length) { if (!rootElementDetected) { // angular doesn't want to attempt to animate elements outside of the application @@ -521,6 +533,18 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { // there is no need to continue traversing at this point if (parentAnimationDetected && animateChildren === false) break; + if (!rootElementDetected) { + // angular doesn't want to attempt to animate elements outside of the application + // therefore we need to ensure that the rootElement is an ancestor of the current element + rootElementDetected = isMatchingElement(parent, $rootElement); + if (!rootElementDetected) { + parentHost = parent.data(NG_ANIMATE_PIN_DATA); + if (parentHost) { + parent = parentHost; + } + } + } + if (!bodyElementDetected) { // we also need to ensure that the element is or will be apart of the body element // otherwise it is pointless to even issue an animation to be rendered diff --git a/src/ngAnimate/shared.js b/src/ngAnimate/shared.js index eb83dc87e341..bfa5a80c5916 100644 --- a/src/ngAnimate/shared.js +++ b/src/ngAnimate/shared.js @@ -22,6 +22,13 @@ var isPromiseLike = function(p) { return p && p.then ? true : false; } +function assertArg(arg, name, reason) { + if (!arg) { + throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required")); + } + return arg; +} + function mergeClasses(a,b) { if (!a && !b) return ''; if (!a) return b; diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index d162b079e58d..5a0d730cf4ea 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -1114,6 +1114,74 @@ describe("animations", function() { })); }); + describe('.pin()', function() { + var capturedAnimation; + + beforeEach(module(function($provide) { + capturedAnimation = null; + $provide.factory('$$animation', function($$AnimateRunner) { + return function() { + capturedAnimation = arguments; + return new $$AnimateRunner(); + }; + }); + })); + + it('should allow an element to pinned elsewhere and still be available in animations', + inject(function($animate, $compile, $document, $rootElement, $rootScope) { + + var body = jqLite($document[0].body); + var innerParent = jqLite('
    '); + body.append(innerParent); + innerParent.append($rootElement); + + var element = jqLite('
    '); + body.append(element); + + $animate.addClass(element, 'red'); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); + + $animate.pin(element, $rootElement); + + $animate.addClass(element, 'blue'); + $rootScope.$digest(); + expect(capturedAnimation).toBeTruthy(); + + dealoc(element); + })); + + it('should adhere to the disabled state of the hosted parent when an element is pinned', + inject(function($animate, $compile, $document, $rootElement, $rootScope) { + + var body = jqLite($document[0].body); + var innerParent = jqLite('
    '); + body.append(innerParent); + innerParent.append($rootElement); + var innerChild = jqLite('
    '); + $rootElement.append(innerChild); + + var element = jqLite('
    '); + body.append(element); + + $animate.pin(element, innerChild); + + $animate.enabled(innerChild, false); + + $animate.addClass(element, 'blue'); + $rootScope.$digest(); + expect(capturedAnimation).toBeFalsy(); + + $animate.enabled(innerChild, true); + + $animate.addClass(element, 'red'); + $rootScope.$digest(); + expect(capturedAnimation).toBeTruthy(); + + dealoc(element); + })); + }); + describe('callbacks', function() { var captureLog = []; var capturedAnimation = []; From 521d889ced05b625dadefd6b0ed245d43de5b688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Thu, 16 Apr 2015 11:33:59 -0700 Subject: [PATCH 208/489] fix(ngAnimate): close parent animations only when there are classes to resolve Previously if a parent animation was cancelled then it would not resolve the runner when that happens. This is now fixed in this patch. Another fix in this patch ensures that a parent animation is only cancelled if the animation contains any classes to resolve. This prevents inline animations from being cancelled. --- src/ngAnimate/animateQueue.js | 3 ++- test/ngAnimate/animateSpec.js | 37 +++++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/ngAnimate/animateQueue.js b/src/ngAnimate/animateQueue.js index 1b914485edba..00dd4e3e62db 100644 --- a/src/ngAnimate/animateQueue.js +++ b/src/ngAnimate/animateQueue.js @@ -388,6 +388,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { // it, otherwise if it's the same then the end result will be the same too if (animationCancelled || (isStructural && animationDetails.event !== event)) { options.domOperation(); + runner.end(); } return; @@ -482,7 +483,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { // animations to properly function (otherwise any CSS selectors may not work) function examineParentAnimation(node, animationDetails) { // enter/leave/move always have priority - if (animationDetails.structural) return; + if (animationDetails.structural || !hasAnimationClasses(animationDetails.options)) return; if (animationDetails.state === RUNNING_STATE) { animationDetails.runner.end(); diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index 5a0d730cf4ea..cf4d4fefd45a 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -510,16 +510,49 @@ describe("animations", function() { describe('parent animations', function() { it('should immediately end a pre-digest parent class-based animation if a structural child is active', - inject(function($rootScope, $animate) { + inject(function($rootScope, $animate, $$rAF) { parent.append(element); var child = jqLite('
    '); - $animate.addClass(parent, 'abc'); + + var itsOver = false; + $animate.addClass(parent, 'abc').done(function() { + itsOver = true; + }); $animate.enter(child, element); + $$rAF.flush(); + + expect(itsOver).toBe(false); $rootScope.$digest(); expect(parent).toHaveClass('abc'); + expect(itsOver).toBe(true); + })); + + it('should not end a pre-digest parent animation if it does not have any classes to add/remove', + inject(function($rootScope, $animate, $$rAF) { + + parent.append(element); + var child = jqLite('
    '); + var runner = $animate.animate(parent, + { height:'0px' }, + { height:'100px' }); + + var doneCount = 0; + runner.done(function() { + doneCount++; + }); + + var runner2 = $animate.enter(child, element); + runner2.done(function() { + doneCount++; + }); + + $rootScope.$digest(); + $$rAF.flush(); + + expect(doneCount).toBe(0); })); it('should immediately end a parent class-based animation if a structural child is active', From 4f5452b2dbbd76c58bf2afccac9268f61f38c4f2 Mon Sep 17 00:00:00 2001 From: ElRaph Date: Thu, 16 Apr 2015 14:39:47 +0200 Subject: [PATCH 209/489] docs(ngMessages): missing quotation mark... ... let the example fail. It seem to be a copy paste fail. --- src/ngMessages/messages.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ngMessages/messages.js b/src/ngMessages/messages.js index aa3f0366b83f..6dab3a2ff503 100644 --- a/src/ngMessages/messages.js +++ b/src/ngMessages/messages.js @@ -275,7 +275,7 @@ angular.module('ngMessages', []) * * * - * * ... * ... * ... @@ -303,7 +303,7 @@ angular.module('ngMessages', []) * *
    myForm.myName.$error = {{ myForm.myName.$error | json }}
    * - *
    *
    You did not enter a field
    *
    Your field is too short
    *
    Your field is too long
    @@ -492,12 +492,12 @@ angular.module('ngMessages', []) * @usage * ```html * - * * ... * * * - * * ... * * ``` @@ -548,13 +548,13 @@ angular.module('ngMessages', []) * @usage * ```html * - * * ... * ... * * * - * * ... * ... * From dc70d71cd198eeab8bf0a2dc3bc670b85832ea65 Mon Sep 17 00:00:00 2001 From: Melvin Date: Thu, 16 Apr 2015 15:27:32 +0530 Subject: [PATCH 210/489] docs(ngMessages): fix remote include naming mismatch ng-messages-include was loading the wrong template. --- src/ngMessages/messages.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ngMessages/messages.js b/src/ngMessages/messages.js index 6dab3a2ff503..d65925cd260a 100644 --- a/src/ngMessages/messages.js +++ b/src/ngMessages/messages.js @@ -119,7 +119,7 @@ var jqLite = angular.element; *
    Your email address is invalid
    * * - *
    + *
    *
    * * ``` From e1a5dd1e785a33eabb88e3f36ff84afd6656c353 Mon Sep 17 00:00:00 2001 From: John Hoffman Date: Thu, 16 Apr 2015 09:27:11 -0600 Subject: [PATCH 211/489] fix($http): stop coercing falsy HTTP request bodies to null / empty body Closes #11552 Closes #11593 --- src/ng/httpBackend.js | 2 +- test/ng/httpBackendSpec.js | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/ng/httpBackend.js b/src/ng/httpBackend.js index 4eb872cd5f11..8bfd85516807 100644 --- a/src/ng/httpBackend.js +++ b/src/ng/httpBackend.js @@ -109,7 +109,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc } } - xhr.send(post || null); + xhr.send(post); } if (timeout > 0) { diff --git a/test/ng/httpBackendSpec.js b/test/ng/httpBackendSpec.js index 12ceed5beb01..abe40d176bff 100644 --- a/test/ng/httpBackendSpec.js +++ b/test/ng/httpBackendSpec.js @@ -50,6 +50,23 @@ describe('$httpBackend', function() { expect(xhr.$$data).toBe(null); }); + it('should pass the correct falsy value to send if falsy body is set (excluding NaN)', function() { + var values = [false, 0, "", null, undefined]; + angular.forEach(values, function(value) { + $backend('GET', '/some-url', value, noop); + xhr = MockXhr.$$lastInstance; + + expect(xhr.$$data).toBe(value); + }); + }); + + it('should pass NaN to send if NaN body is set', function() { + $backend('GET', '/some-url', NaN, noop); + xhr = MockXhr.$$lastInstance; + + expect(isNaN(xhr.$$data)).toEqual(true); + }); + it('should call completion function with xhr.statusText if present', function() { callback.andCallFake(function(status, response, headers, statusText) { expect(statusText).toBe('OK'); From 3e45733c78afa822c89d178a43fd35986313650d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Wed, 15 Apr 2015 15:13:22 -0700 Subject: [PATCH 212/489] docs($animate): include docs for `on`, `off`, `enabled` and `cancel` --- src/ng/animate.js | 91 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/src/ng/animate.js b/src/ng/animate.js index 4901dfb15550..2a9b6e0d549b 100644 --- a/src/ng/animate.js +++ b/src/ng/animate.js @@ -271,7 +271,59 @@ var $AnimateProvider = ['$provide', function($provide) { return { // we don't call it directly since non-existant arguments may // be interpreted as null within the sub enabled function + + /** + * + * @ngdoc method + * @name $animate#on + * @kind function + * @description Sets up an event listener to fire whenever the animation event (enter, leave, move, etc...) + * has fired on the given element or among any of its children. Once the listener is fired, the provided callback + * is fired with the following params: + * + * ```js + * $animate.on('enter', container, + * function callback(element, phase) { + * // cool we detected an enter animation within the container + * } + * ); + * ``` + * + * @param {string} event the animation event that will be captured (e.g. enter, leave, move, addClass, removeClass, etc...) + * @param {DOMElement} container the container element that will capture each of the animation events that are fired on itself + * as well as among its children + * @param {Function} callback the callback function that will be fired when the listener is triggered + * + * The arguments present in the callback function are: + * * `element` - The captured DOM element that the animation was fired on. + * * `phase` - The phase of the animation. The two possible phases are **start** (when the animation starts) and **close** (when it ends). + */ on: $$animateQueue.on, + + /** + * + * @ngdoc method + * @name $animate#off + * @kind function + * @description Deregisters an event listener based on the event which has been associated with the provided element. This method + * can be used in three different ways depending on the arguments: + * + * ```js + * // remove all the animation event listeners listening for `enter` + * $animate.off('enter'); + * + * // remove all the animation event listeners listening for `enter` on the given element and its children + * $animate.off('enter', container); + * + * // remove the event listener function provided by `listenerFn` that is set + * // to listen for `enter` on the given `element` as well as its children + * $animate.off('enter', container, callback); + * ``` + * + * @param {string} event the animation event (e.g. enter, leave, move, addClass, removeClass, etc...) + * @param {DOMElement=} container the container element the event listener was placed on + * @param {Function=} callback the callback function that was registered as the listener + */ off: $$animateQueue.off, /** @@ -292,10 +344,47 @@ var $AnimateProvider = ['$provide', function($provide) { */ pin: $$animateQueue.pin, + /** + * + * @ngdoc method + * @name $animate#enabled + * @kind function + * @description Used to get and set whether animations are enabled or not on the entire application or on an element and its children. This + * function can be called in four ways: + * + * ```js + * // returns true or false + * $animate.enabled(); + * + * // changes the enabled state for all animations + * $animate.enabled(false); + * $animate.enabled(true); + * + * // returns true or false if animations are enabled for an element + * $animate.enabled(element); + * + * // changes the enabled state for an element and its children + * $animate.enabled(element, true); + * $animate.enabled(element, false); + * ``` + * + * @param {DOMElement=} element the element that will be considered for checking/setting the enabled state + * @param {boolean=} enabled whether or not the animations will be enabled for the element + * + * @return {boolean} whether or not animations are enabled + */ enabled: $$animateQueue.enabled, + /** + * @ngdoc method + * @name $animate#cancel + * @kind function + * @description Cancels the provided animation. + * + * @param {Promise} animationPromise The animation promise that is returned when an animation is started. + */ cancel: function(runner) { - runner.cancel && runner.end(); + runner.end && runner.end(); }, /** From b8c79ade601a8bdcb24acd157078934729820637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Tue, 14 Apr 2015 11:39:22 -0700 Subject: [PATCH 213/489] docs(MIGRATION): add notes for the migration from 1.3 to 1.4 --- docs/content/guide/migration.ngdoc | 295 +++++++++++++++++++++++++++++ 1 file changed, 295 insertions(+) diff --git a/docs/content/guide/migration.ngdoc b/docs/content/guide/migration.ngdoc index 25f3bcd681af..7098bff2ac93 100644 --- a/docs/content/guide/migration.ngdoc +++ b/docs/content/guide/migration.ngdoc @@ -13,6 +13,301 @@ which drives many of these changes. * Several new features, especially animations, would not be possible without a few changes. * Finally, some outstanding bugs were best fixed by changing an existing API. +# Migrating from 1.3 to 1.4 + +Angular 1.4 fixes the major animation issues and introduces some breaking changes for `cookies`, `ngMessages`, +`$compile`, `ngRepeat`, `ngOptions `and some fixes to core filters: `limitTo` and `filter`. + +The reason for the ngAnimate refactor was to fix timing issues and to expose new APIs to allow +for developers to construct more versatile animations. We now have access to `$animateCss` +and the many timing-oriented bugs were fixed which resulted in more smoother animations. +If animation is something of interest, then please read over the breaking changes below for animations when +`ngAnimate` is used. + +ngMessages has also been upgraded to allow for dynamic message resolution. This handy feature allows for developers +to render error messages with ngMessages that are listed with a directive such as ngRepeat. A great usecase for this +involves pulling error message data from a server and then displaying that data via the mechanics of ngMessages. Be +sure to read the breaking change involved with `ngMessagesInclude` to upgrade your template code. + +Other changes, such as the ordering of elements with ngRepeat and ngOptions, may also effect the behavior of your +application. And be sure to also read up on the changes to `$cookies`. The migration jump from 1.3 to 1.4 should be +relatively straightforward otherwise. + + + + +## Animation (`ngAnimate`) + +Animation in 1.4 have been refactored internally and the API has stayed much the same. There are, however, +some breaking changes that need to be addressed when any Angular animation code is upgraded to work in 1.4. + +Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef), +JavaSript and CSS animations can no longer be run in +parallel. With earlier versions of ngAnimate, both CSS and JS animations +would be run together when multiple animations were detected. This +feature has now been removed, however, the same effect, with even more +possibilities, can be achieved by injecting `$animateCss` into a +JavaScript-defined animation and creating custom CSS-based animations +from there. + +By using `$animateCss` inside of a JavaScript animation in Angular 1.4, we can trigger custom CSS-based animations +directly from our JavaScript code. + +```js +ngModule.animation('.slide-animation', ['$animateCss', function($animateCss) { + return { + enter: function(element, doneFn) { + // this will trigger a `.ng-enter` and `.ng-enter-active` CSS animation + var animation = $animateCss(element, { + event: 'enter' + // any other CSS-related properties + // addClass: 'some-class', + // removeClass: 'some-other-class', + // from: {}, + // to: {} + }); + + // make sure to read the ngAnimate docs to understand how this works + animation.start().done(doneFn); + } + } +}]); +``` + +{@link ngAnimate.$animateCss Click here to learn how to use $animateCss in your animation code} + +Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef), +animation-related callbacks are now fired on `$animate.on` instead of directly being on the element. + +```js +// < 1.4 +element.on('$animate:before', function(e, data) { + if (data.event === 'enter') { ... } +}); +element.off('$animate:before', fn); + +// 1.4+ +$animate.on(element, 'enter', function(data) { + //... +}); +$animate.off(element, 'enter', fn); +``` + +Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef), +the function params for `$animate.enabled()` when an element is used are now flipped. This fix allows +the function to act as a getter when a single element param is provided. + +```js +// < 1.4 +$animate.enabled(false, element); + +// 1.4+ +$animate.enabled(element, false); +``` + +Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef), +in addition to disabling the children of the element, `$animate.enabled(element, false)` will now also +disable animations on the element itself. + +Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef), +there is no need to call `$scope.$apply` or `$scope.$digest` inside of a animation promise callback anymore +since the promise is resolved within a digest automatically. (Not to worry, any extra digests will not be +run unless the promise is used.) + +```js +// < 1.4 +$animate.enter(element).then(function() { + $scope.$apply(function() { + $scope.explode = true; + }); +}); + +// 1.4+ +$animate.enter(element).then(function() { + $scope.explode = true; +}); +``` + +Due to [c8700f04](https://github.com/angular/angular.js/commit/c8700f04fb6fb5dc21ac24de8665c0476d6db5ef), +when an enter, leave or move animation is triggered then it will always end any pending or active parent +class based animations (animations triggered via ngClass) in order to ensure that any CSS styles are resolved in time. + + + + +## Forms (`ngMessages`, `ngOptions`) + +### ngMessages +The ngMessages module has also been subject to an internal refactor to allow the feature to be more flexible +and compatible with dynamic message data. The ngMessage directive now supports a new attribute called `ng-message-exp` +which will evaluate an expression and will keep track of that expression as it changes in order to re-evaluate +the listed messages. + +There is only one breaking change. Please consider the following when including remote message templates via `ng-messages-include`: + +Due to [c9a4421f](https://github.com/angular/angular.js/commit/c9a4421fc3c97448527eadef1f42eb2f487ec2e0), +the `ngMessagesInclude` attribute has now been removed and cannot be used in the same element containing +the `ngMessages` directive. Instead, `ngMessagesInclude` is to be used on its own element inline with +other inline messages situated as children within the `ngMessages` container directive. + +```html + +
    +
    Your message is required
    +
    + + +
    +
    Your message is required
    +
    +
    +``` + +Depending on where the `ngMessagesInclude` directive is placed it will be prioritized inline with the other messages +before and after it. + +### ngOptions + +Due to [7fda214c](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef), +when `ngOptions` renders the option values within the DOM, the resulting HTML code is different. Normally this +should not affect your application at all, however, if your code relies on inspecing the value property of `
    NamePhone
    + + + + + + + + + {% for param in params %} + + + + + + {% endfor %} + +
    ParamTypeDetails
    + {$ param.name $} + {% if param.alias %}| {$ param.alias $}{% endif %} + {% if param.optional %}
    (optional)
    {% endif %} +
    + {$ typeList(param.typeList) $} + + {$ param.description | marked $} + {% if param.defaultValue %}

    (default: {$ param.defaultValue $})

    {% endif %} +
    +{% endmacro -%} + + +{%- macro directiveParam(name, type, join, sep) %} + {%- if type.optional %}[{% endif -%} + {$ name | dashCase $}{$ join $}{$ type.name $}{$ sep $} + {%- if type.optional %}]{% endif -%} +{% endmacro -%} + +{%- macro functionSyntax(fn) %} + {%- set sep = joiner(', ') -%} + {% marked -%} + `{$ fn.name $}({%- for param in fn.params %}{$ sep() $} + {%- if param.type.optional %}[{% endif -%} + {$ param.name $} + {%- if param.type.optional %}]{% endif -%} + {% endfor %});` + {%- endmarked %} +{% endmacro -%} + +{%- macro typeInfo(fn) -%} + + + + + +
    {$ typeList(fn.typeList) $}{$ fn.description | marked $}
    +{%- endmacro -%} From d08102de9b77376c02892df856a89d724ad869d5 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Wed, 29 Apr 2015 22:57:16 -0700 Subject: [PATCH 242/489] docs(ngAnimate): fix typo in 'greetingBox' directive Closes #11766 Closes #11747 --- src/ngAnimate/module.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ngAnimate/module.js b/src/ngAnimate/module.js index 86ecf5c9a21d..9d54b4faad5a 100644 --- a/src/ngAnimate/module.js +++ b/src/ngAnimate/module.js @@ -601,7 +601,7 @@ * imagine we have a greeting box that shows and hides itself when the data changes * * ```html - * Hi there + * Hi there * ``` * * ```js From 5a1ed03aa97960f8f430be4e1e4be0d7fe7dee05 Mon Sep 17 00:00:00 2001 From: thatType Date: Wed, 22 Apr 2015 22:14:10 -0400 Subject: [PATCH 243/489] docs(contribute): transpose "however" and "it's" Transpose "however" and "it's" on line 156 for slightly better readability Closes #11686 --- docs/content/misc/contribute.ngdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/misc/contribute.ngdoc b/docs/content/misc/contribute.ngdoc index c4fcdd121b6a..b3f125f4dd63 100644 --- a/docs/content/misc/contribute.ngdoc +++ b/docs/content/misc/contribute.ngdoc @@ -153,7 +153,7 @@ grunt test:unit --browsers Opera,Firefox Note there should be _no spaces between browsers_. `Opera, Firefox` is INVALID. -During development it's however more productive to continuously run unit tests every time the source or test files +During development, however, it's more productive to continuously run unit tests every time the source or test files change. To execute tests in this mode run: 1. To start the Karma server, capture Chrome browser and run unit tests, run: From 89088b5ad555935f485dd6cd39644b7f5008dc5b Mon Sep 17 00:00:00 2001 From: Ron Tsui Date: Tue, 21 Apr 2015 21:09:47 -0700 Subject: [PATCH 244/489] style(docs): improve formatting in code comment Closes #11674 --- docs/config/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/config/index.js b/docs/config/index.js index e95d74ce50ae..86f0d03c2db4 100644 --- a/docs/config/index.js +++ b/docs/config/index.js @@ -6,7 +6,7 @@ var packagePath = __dirname; var Package = require('dgeni').Package; // Create and export a new Dgeni package called angularjs. This package depends upon -// the ngdoc,nunjucks and examples packages defined in the dgeni-packages npm module. +// the ngdoc, nunjucks, and examples packages defined in the dgeni-packages npm module. module.exports = new Package('angularjs', [ require('dgeni-packages/ngdoc'), require('dgeni-packages/nunjucks'), From 9f0176131ab7a88f26515632455aefb8b249c00d Mon Sep 17 00:00:00 2001 From: Steve Mao Date: Tue, 21 Apr 2015 11:04:16 +1000 Subject: [PATCH 245/489] docs(ngCloak): remove information for ie7 IE7 is not supported. Also change `#template2` text to `'world'`. Closes #11661 --- src/ng/directive/ngCloak.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/ng/directive/ngCloak.js b/src/ng/directive/ngCloak.js index bf19117a3336..19bd25c83252 100644 --- a/src/ng/directive/ngCloak.js +++ b/src/ng/directive/ngCloak.js @@ -33,17 +33,13 @@ * document; alternatively, the css rule above must be included in the external stylesheet of the * application. * - * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they - * cannot match the `[ng\:cloak]` selector. To work around this limitation, you must add the css - * class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below. - * * @element ANY * * @example
    {{ 'hello' }}
    -
    {{ 'hello IE7' }}
    +
    {{ 'world' }}
    it('should remove the template directive and css class', function() { From c8c279bb86f86a6dc5b7f6abb955d6de98589be0 Mon Sep 17 00:00:00 2001 From: Jeff Wesson Date: Mon, 13 Apr 2015 17:43:58 -0700 Subject: [PATCH 246/489] docs(form): replace obsolete tt element Removes the [**obsolete** HTML Teletype Text Element ``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tt) and replaces it with [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code). This adds more semanticity and is part of the [HTML5 specification](http://www.w3.org/TR/html5/text-level-semantics.html#the-code-element). Closes #11570 --- src/ng/directive/form.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ng/directive/form.js b/src/ng/directive/form.js index 12b844a5f712..9c7f52564c91 100644 --- a/src/ng/directive/form.js +++ b/src/ng/directive/form.js @@ -415,11 +415,11 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
    userType: Required!
    - userType = {{userType}}
    - myForm.input.$valid = {{myForm.input.$valid}}
    - myForm.input.$error = {{myForm.input.$error}}
    - myForm.$valid = {{myForm.$valid}}
    - myForm.$error.required = {{!!myForm.$error.required}}
    + userType = {{userType}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    From 68c136d3e653e3c0f3626b9bd496bcfd00232c50 Mon Sep 17 00:00:00 2001 From: Rodrigo Parra Date: Fri, 3 Apr 2015 20:56:48 -0400 Subject: [PATCH 247/489] docs(ngSwitch): Replace tt tag with code tag Use of tt is discouraged, see: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tt http://www.w3.org/wiki/HTML/Elements/tt Closes #11509 --- src/ng/directive/ngSwitch.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ng/directive/ngSwitch.js b/src/ng/directive/ngSwitch.js index 38bc5a5537c8..79155f433af5 100644 --- a/src/ng/directive/ngSwitch.js +++ b/src/ng/directive/ngSwitch.js @@ -43,7 +43,7 @@ * * @scope * @priority 1200 - * @param {*} ngSwitch|on expression to match against ng-switch-when. + * @param {*} ngSwitch|on expression to match against ng-switch-when. * On child elements add: * * * `ngSwitchWhen`: the case statement to match against. If match then this @@ -60,7 +60,7 @@
    - selection={{selection}} + selection={{selection}}
    From 15e242677fe294a1e2af2852bb070bf86fc42d8d Mon Sep 17 00:00:00 2001 From: Leonardo Braga Date: Wed, 1 Apr 2015 20:58:52 -0400 Subject: [PATCH 248/489] docs(ngModel): improve formatting of `$modelValue` Closes #11483 --- src/ng/directive/ngModel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ng/directive/ngModel.js b/src/ng/directive/ngModel.js index 8836093195f9..b3d23a93d877 100644 --- a/src/ng/directive/ngModel.js +++ b/src/ng/directive/ngModel.js @@ -504,7 +504,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ * If the validity changes to invalid, the model will be set to `undefined`, * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`. * If the validity changes to valid, it will set the model to the last available valid - * modelValue, i.e. either the last parsed value or the last value set from the scope. + * `$modelValue`, i.e. either the last parsed value or the last value set from the scope. */ this.$validate = function() { // ignore $validate before model is initialized From 3e45bc91b8a99037c705e448d55821327196fd1d Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Thu, 30 Apr 2015 13:14:46 +0100 Subject: [PATCH 249/489] fix(ngOptions): iterate over the options collection in the same way as `ngRepeat` In `ngRepeat` if the object to be iterated over is "array-like" then it only iterates over the numerical indexes rather than every key on the object. This prevents "helper" methods from being included in the rendered collection. This commit changes `ngOptions` to iterate in the same way. BREAKING CHANGE: Although it is unlikely that anyone is using it in this way, this change does change the behaviour of `ngOptions` in the following case: * you are iterating over an array-like object, using the array form of the `ngOptions` syntax (`item.label for item in items`) and that object contains non-numeric property keys. In this case these properties with non-numeric keys will be ignored. ** Here array-like is defined by the result of a call to this internal function: https://github.com/angular/angular.js/blob/v1.4.0-rc.1/src/Angular.js#L198-L211 ** To get the desired behaviour you need to iterate using the object form of the `ngOptions` syntax (`value.label` for (key, value) in items)`). Closes #11733 --- src/ng/directive/ngOptions.js | 22 ++++++++++++---- test/ng/directive/ngOptionsSpec.js | 41 ++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/ng/directive/ngOptions.js b/src/ng/directive/ngOptions.js index 5f67c950e7e1..6d776fb87ac6 100644 --- a/src/ng/directive/ngOptions.js +++ b/src/ng/directive/ngOptions.js @@ -325,13 +325,25 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { // The option values were already computed in the `getWatchables` fn, // which must have been called to trigger `getOptions` var optionValues = valuesFn(scope) || []; + var optionValuesKeys; - var keys = Object.keys(optionValues); - keys.forEach(function getOption(key) { - // Ignore "angular" properties that start with $ or $$ - if (key.charAt(0) === '$') return; + if (!keyName && isArrayLike(optionValues)) { + optionValuesKeys = optionValues; + } else { + // if object, extract keys, in enumeration order, unsorted + optionValuesKeys = []; + for (var itemKey in optionValues) { + if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') { + optionValuesKeys.push(itemKey); + } + } + } + var optionValuesLength = optionValuesKeys.length; + + for (var index = 0; index < optionValuesLength; index++) { + var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index]; var value = optionValues[key]; var locals = getLocals(value, key); var viewValue = viewValueFn(scope, locals); @@ -343,7 +355,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { optionItems.push(optionItem); selectValueMap[selectValue] = optionItem; - }); + } return { items: optionItems, diff --git a/test/ng/directive/ngOptionsSpec.js b/test/ng/directive/ngOptionsSpec.js index 2998ad7aa577..d0edd7be8e76 100644 --- a/test/ng/directive/ngOptionsSpec.js +++ b/test/ng/directive/ngOptionsSpec.js @@ -180,6 +180,47 @@ describe('ngOptions', function() { }); + it('should not include properties with non-numeric keys in array-like collections when using array syntax', function() { + createSelect({ + 'ng-model':'selected', + 'ng-options':'value for value in values' + }); + + scope.$apply(function() { + scope.values = { 0: 'X', 1: 'Y', 2: 'Z', 'a': 'A', length: 3}; + scope.selected = scope.values[1]; + }); + + var options = element.find('option'); + expect(options.length).toEqual(3); + expect(options.eq(0)).toEqualOption('X'); + expect(options.eq(1)).toEqualOption('Y'); + expect(options.eq(2)).toEqualOption('Z'); + + }); + + + it('should include properties with non-numeric keys in array-like collections when using object syntax', function() { + createSelect({ + 'ng-model':'selected', + 'ng-options':'value for (key, value) in values' + }); + + scope.$apply(function() { + scope.values = { 0: 'X', 1: 'Y', 2: 'Z', 'a': 'A', length: 3}; + scope.selected = scope.values[1]; + }); + + var options = element.find('option'); + expect(options.length).toEqual(5); + expect(options.eq(0)).toEqualOption('X'); + expect(options.eq(1)).toEqualOption('Y'); + expect(options.eq(2)).toEqualOption('Z'); + expect(options.eq(3)).toEqualOption('A'); + expect(options.eq(4)).toEqualOption(3); + }); + + it('should render an object', function() { createSelect({ 'ng-model': 'selected', From 7cc2c9f77bb7a6d3734adba798ec726ce0f8c19a Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 30 Apr 2015 16:19:59 -0600 Subject: [PATCH 250/489] docs(ngJq): update to indicate common pitfall change docs for ngJq so it mentions that the placement of the directive is important with regards to the angular script. Closes #11779 Closes #11780 --- src/Angular.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Angular.js b/src/Angular.js index c601df7f4067..0d07cc7f0f50 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -964,10 +964,10 @@ var csp = function() { * used to force either jqLite by leaving ng-jq blank or setting the name of * the jquery variable under window (eg. jQuery). * - * Since this directive is global for the angular library, it is recommended - * that it's added to the same element as ng-app or the HTML element, but it is not mandatory. - * It needs to be noted that only the first instance of `ng-jq` will be used and all others - * ignored. + * Since angular looks for this directive when it is loaded (doesn't wait for the + * DOMContentLoaded event), it must be placed on an element that comes before the script + * which loads angular. Also, only the first instance of `ng-jq` will be used and all + * others ignored. * * @example * This example shows how to force jqLite using the `ngJq` directive to the `html` tag. From 242b77b4e494800c315eb39310d8a02edd940e77 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Thu, 30 Apr 2015 22:21:30 +0200 Subject: [PATCH 251/489] docs(changelog): wrap jqLite example containing html with code block This prevents the markdown parser from garbling the input and putting out broken html. Closes #11778 Fixes #11777 Fixes #11539 --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 668b4dc83401..c6cf16b8b4f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4877,7 +4877,7 @@ For more info: http://blog.angularjs.org/2013/12/angularjs-13-new-release-approa - properly toggle multiple classes ([4e73c80b](https://github.com/angular/angular.js/commit/4e73c80b17bd237a8491782bcf9e19f1889e12ed), [#4467](https://github.com/angular/angular.js/issues/4467), [#6448](https://github.com/angular/angular.js/issues/6448)) - - make jqLite('