diff --git a/Gruntfile.js b/Gruntfile.js index 98f0fc69b3..d1293fc1a0 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -16,7 +16,7 @@ module.exports = function(grunt) { grunt.util.linefeed = '\n'; grunt.initConfig({ - ngversion: '1.2.7', + ngversion: '1.2.8', bsversion: '3.0.3', modules: [],//to be filled in by build task pkg: grunt.file.readJSON('package.json'), diff --git a/misc/test-lib/angular-mocks.js b/misc/test-lib/angular-mocks.js index 61b2481a67..90ae186632 100644 --- a/misc/test-lib/angular-mocks.js +++ b/misc/test-lib/angular-mocks.js @@ -1,5 +1,5 @@ /** - * @license AngularJS v1.2.7 + * @license AngularJS v1.2.8 * (c) 2010-2014 Google, Inc. http://angularjs.org * License: MIT */ @@ -2086,6 +2086,20 @@ if(window.jasmine || window.mocha) { * * @param {...Function} fns any number of functions which will be injected using the injector. */ + + + + var ErrorAddingDeclarationLocationStack = function(e, errorForStack) { + this.message = e.message; + this.name = e.name; + if (e.line) this.line = e.line; + if (e.sourceId) this.sourceId = e.sourceId; + if (e.stack && errorForStack) + this.stack = e.stack + '\n' + errorForStack.stack; + if (e.stackArray) this.stackArray = e.stackArray; + }; + ErrorAddingDeclarationLocationStack.prototype.toString = Error.prototype.toString; + window.inject = angular.mock.inject = function() { var blockFns = Array.prototype.slice.call(arguments, 0); var errorForStack = new Error('Declaration Location'); @@ -2106,7 +2120,9 @@ if(window.jasmine || window.mocha) { injector.invoke(blockFns[i] || angular.noop, this); /* jshint +W040 */ } catch (e) { - if(e.stack && errorForStack) e.stack += '\n' + errorForStack.stack; + if (e.stack && errorForStack) { + throw new ErrorAddingDeclarationLocationStack(e, errorForStack); + } throw e; } finally { errorForStack = null; diff --git a/misc/test-lib/angular.js b/misc/test-lib/angular.js index 14559457f7..7856504dd5 100644 --- a/misc/test-lib/angular.js +++ b/misc/test-lib/angular.js @@ -1,5 +1,5 @@ /** - * @license AngularJS v1.2.7 + * @license AngularJS v1.2.8 * (c) 2010-2014 Google, Inc. http://angularjs.org * License: MIT */ @@ -68,7 +68,7 @@ function minErr(module) { return match; }); - message = message + '\nhttp://errors.angularjs.org/1.2.7/' + + message = message + '\nhttp://errors.angularjs.org/1.2.8/' + (module ? module + '/' : '') + code; for (i = 2; i < arguments.length; i++) { message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' + @@ -1833,11 +1833,11 @@ function setupModuleLoader(window) { * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". */ var version = { - full: '1.2.7', // all of these placeholder strings will be replaced by grunt's + full: '1.2.8', // all of these placeholder strings will be replaced by grunt's major: 1, // package task minor: 2, - dot: 7, - codeName: 'emoji-clairvoyance' + dot: 8, + codeName: 'interdimensional-cartography' }; @@ -6648,7 +6648,7 @@ function directiveNormalize(name) { * * * @param {string} name Normalized element attribute name of the property to modify. The name is - * revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr} + * reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr} * property to the original name. * @param {string} value Value to set the attribute to. The value can be an interpolated string. */ @@ -6786,8 +6786,7 @@ function $ControllerProvider() { * @requires $window * * @description - * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document` - * element. + * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object. */ function $DocumentProvider(){ this.$get = ['$window', function(window){ @@ -7126,7 +7125,15 @@ function $HttpProvider() { * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }. * * The defaults can also be set at runtime via the `$http.defaults` object in the same - * fashion. In addition, you can supply a `headers` property in the config object passed when + * fashion. For example: + * + * ``` + * module.run(function($http) { + * $http.defaults.headers.common.Authentication = 'Basic YmVlcDpib29w' + * }); + * ``` + * + * In addition, you can supply a `headers` property in the config object passed when * calling `$http(config)`, which overrides the defaults without changing them globally. * * @@ -7150,7 +7157,9 @@ function $HttpProvider() { * properties. These properties are by default an array of transform functions, which allows you * to `push` or `unshift` a new transformation function into the transformation chain. You can * also decide to completely override any default transformations by assigning your - * transformation functions to these properties directly without the array wrapper. + * transformation functions to these properties directly without the array wrapper. These defaults + * are again available on the $http factory at run-time, which may be useful if you have run-time + * services you wish to be involved in your transformations. * * Similarly, to locally override the request/response transforms, augment the * `transformRequest` and/or `transformResponse` properties of the configuration object passed @@ -7364,7 +7373,8 @@ function $HttpProvider() { * for added security. * * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName - * properties of either $httpProvider.defaults, or the per-request config object. + * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time, + * or the per-request config object. * * * @param {object} config Object describing the request to be made and how it should be @@ -7927,7 +7937,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc } else { completeRequest(callback, status || -2); } - delete callbacks[callbackId]; + callbacks[callbackId] = angular.noop; }); } else { @@ -7944,7 +7954,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc // response is in the cache. the promise api will ensure that to the app code the api is // always async xhr.onreadystatechange = function() { - // onreadystatechange might by called multiple times with readyState === 4 on mobile webkit caused by + // onreadystatechange might get called multiple times with readyState === 4 on mobile webkit caused by // xhrs that are resolved while the app is in the background (see #5426). // since calling completeRequest sets the `xhr` variable to null, we just check if it's not null before // continuing @@ -7957,11 +7967,12 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc if(status !== ABORTED) { responseHeaders = xhr.getAllResponseHeaders(); - response = xhr.responseType ? xhr.response : xhr.responseText; + + // responseText is the old-school way of retrieving response (supported by IE8 & 9) + // response/responseType properties were introduced in XHR Level2 spec (supported by IE10) + response = ('response' in xhr) ? xhr.response : xhr.responseText; } - // responseText is the old-school way of retrieving response (supported by IE8 & 9) - // response/responseType properties were introduced in XHR Level2 spec (supported by IE10) completeRequest(callback, status || xhr.status, response, @@ -7994,14 +8005,14 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc } function completeRequest(callback, status, response, headersString) { - var protocol = urlResolve(url).protocol; - // cancel timeout and subsequent timeout promise resolution timeoutId && $browserDefer.cancel(timeoutId); jsonpDone = xhr = null; - // fix status code for file protocol (it's always 0) - status = (protocol == 'file' && status === 0) ? (response ? 200 : 404) : status; + // fix status code when it is 0 (0 status is undocumented). + // Occurs when accessing file resources. + // On Android 4.1 stock browser it occurs while retrieving files from application cache. + status = (status === 0) ? (response ? 200 : 404) : status; // normalize IE bug (http://bugs.jquery.com/ticket/1450) status = status == 1223 ? 204 : status; @@ -9115,7 +9126,7 @@ function $LocationProvider(){ * Broadcasted before a URL will change. This change can be prevented by calling * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more * details about event object. Upon successful change - * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired. + * {@link ng.$location#events_$locationChangeSuccess $locationChangeSuccess} is fired. * * @param {Object} angularEvent Synthetic event object. * @param {string} newUrl New URL @@ -10306,16 +10317,20 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) { if (pathVal == null) return pathVal; pathVal = pathVal[key0]; - if (pathVal == null) return key1 ? undefined : pathVal; + if (!key1) return pathVal; + if (pathVal == null) return undefined; pathVal = pathVal[key1]; - if (pathVal == null) return key2 ? undefined : pathVal; + if (!key2) return pathVal; + if (pathVal == null) return undefined; pathVal = pathVal[key2]; - if (pathVal == null) return key3 ? undefined : pathVal; + if (!key3) return pathVal; + if (pathVal == null) return undefined; pathVal = pathVal[key3]; - if (pathVal == null) return key4 ? undefined : pathVal; + if (!key4) return pathVal; + if (pathVal == null) return undefined; pathVal = pathVal[key4]; return pathVal; @@ -10336,8 +10351,9 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) { } pathVal = pathVal.$$v; } - if (pathVal == null) return key1 ? undefined : pathVal; + if (!key1) return pathVal; + if (pathVal == null) return undefined; pathVal = pathVal[key1]; if (pathVal && pathVal.then) { promiseWarning(fullExp); @@ -10348,8 +10364,9 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) { } pathVal = pathVal.$$v; } - if (pathVal == null) return key2 ? undefined : pathVal; + if (!key2) return pathVal; + if (pathVal == null) return undefined; pathVal = pathVal[key2]; if (pathVal && pathVal.then) { promiseWarning(fullExp); @@ -10360,8 +10377,9 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) { } pathVal = pathVal.$$v; } - if (pathVal == null) return key3 ? undefined : pathVal; + if (!key3) return pathVal; + if (pathVal == null) return undefined; pathVal = pathVal[key3]; if (pathVal && pathVal.then) { promiseWarning(fullExp); @@ -10372,8 +10390,9 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) { } pathVal = pathVal.$$v; } - if (pathVal == null) return key4 ? undefined : pathVal; + if (!key4) return pathVal; + if (pathVal == null) return undefined; pathVal = pathVal[key4]; if (pathVal && pathVal.then) { promiseWarning(fullExp); @@ -11371,7 +11390,7 @@ function $RootScopeProvider(){ } else { ChildScope = function() {}; // should be anonymous; This is so that when the minifier munges // the name it does not become random set of chars. This will then show up as class - // name in the debugger. + // name in the web inspector. ChildScope.prototype = this; child = new ChildScope(); child.$id = nextUid(); @@ -11472,7 +11491,7 @@ function $RootScopeProvider(){ // No digest has been run so the counter will be zero expect(scope.foodCounter).toEqual(0); - // Run the digest but since food has not changed cout will still be zero + // Run the digest but since food has not changed count will still be zero scope.$digest(); expect(scope.foodCounter).toEqual(0); @@ -13895,8 +13914,8 @@ function $FilterProvider($provide) { * * Can be one of: * - * - `string`: Predicate that results in a substring match using the value of `expression` - * string. All strings or objects with string properties in `array` that contain this string + * - `string`: The string is evaluated as an expression and the resulting value is used for substring match against + * the contents of the `array`. All strings or objects with string properties in `array` that contain this string * will be returned. The predicate can be negated by prefixing the string with `!`. * * - `Object`: A pattern object can be used to filter specific properties on objects contained @@ -14054,23 +14073,12 @@ function filterFilter() { case "object": // jshint +W086 for (var key in expression) { - if (key == '$') { - (function() { - if (!expression[key]) return; - var path = key; - predicates.push(function(value) { - return search(value, expression[path]); - }); - })(); - } else { - (function() { - if (typeof(expression[key]) == 'undefined') { return; } - var path = key; - predicates.push(function(value) { - return search(getter(value,path), expression[path]); - }); - })(); - } + (function(path) { + if (typeof expression[path] == 'undefined') return; + predicates.push(function(value) { + return search(path == '$' ? value : getter(value, path), expression[path]); + }); + })(key); } break; case 'function': @@ -15191,12 +15199,10 @@ forEach(BOOLEAN_ATTR, function(propName, attrName) { ngAttributeAliasDirectives[normalized] = function() { return { priority: 100, - compile: function() { - return function(scope, element, attr) { - scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) { - attr.$set(attrName, !!value); - }); - }; + link: function(scope, element, attr) { + scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) { + attr.$set(attrName, !!value); + }); } }; }; @@ -15476,10 +15482,10 @@ function FormController(element, attrs) { * * * # CSS classes - * - `ng-valid` Is set if the form is valid. - * - `ng-invalid` Is set if the form is invalid. - * - `ng-pristine` Is set if the form is pristine. - * - `ng-dirty` Is set if the form is dirty. + * - `ng-valid` is set if the form is valid. + * - `ng-invalid` is set if the form is invalid. + * - `ng-pristine` is set if the form is pristine. + * - `ng-dirty` is set if the form is dirty. * * * # Submitting a form and preventing the default action @@ -15996,6 +16002,12 @@ var inputType = { 'reset': noop }; +// A helper function to call $setValidity and return the value / undefined, +// a pattern that is repeated a lot in the input validation logic. +function validate(ctrl, validatorName, validity, value){ + ctrl.$setValidity(validatorName, validity); + return validity ? value : undefined; +} function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { // In composition mode, users are still inputing intermediate text buffer, @@ -16080,22 +16092,15 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { patternValidator, match; - var validate = function(regexp, value) { - if (ctrl.$isEmpty(value) || regexp.test(value)) { - ctrl.$setValidity('pattern', true); - return value; - } else { - ctrl.$setValidity('pattern', false); - return undefined; - } - }; - if (pattern) { + var validateRegex = function(regexp, value) { + return validate(ctrl, 'pattern', ctrl.$isEmpty(value) || regexp.test(value), value); + }; match = pattern.match(/^\/(.*)\/([gim]*)$/); if (match) { pattern = new RegExp(match[1], match[2]); patternValidator = function(value) { - return validate(pattern, value); + return validateRegex(pattern, value); }; } else { patternValidator = function(value) { @@ -16106,7 +16111,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { 'Expected {0} to be a RegExp but was {1}. Element: {2}', pattern, patternObj, startingTag(element)); } - return validate(patternObj, value); + return validateRegex(patternObj, value); }; } @@ -16118,13 +16123,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { if (attr.ngMinlength) { var minlength = int(attr.ngMinlength); var minLengthValidator = function(value) { - if (!ctrl.$isEmpty(value) && value.length < minlength) { - ctrl.$setValidity('minlength', false); - return undefined; - } else { - ctrl.$setValidity('minlength', true); - return value; - } + return validate(ctrl, 'minlength', ctrl.$isEmpty(value) || value.length >= minlength, value); }; ctrl.$parsers.push(minLengthValidator); @@ -16135,13 +16134,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { if (attr.ngMaxlength) { var maxlength = int(attr.ngMaxlength); var maxLengthValidator = function(value) { - if (!ctrl.$isEmpty(value) && value.length > maxlength) { - ctrl.$setValidity('maxlength', false); - return undefined; - } else { - ctrl.$setValidity('maxlength', true); - return value; - } + return validate(ctrl, 'maxlength', ctrl.$isEmpty(value) || value.length <= maxlength, value); }; ctrl.$parsers.push(maxLengthValidator); @@ -16170,13 +16163,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { if (attr.min) { var minValidator = function(value) { var min = parseFloat(attr.min); - if (!ctrl.$isEmpty(value) && value < min) { - ctrl.$setValidity('min', false); - return undefined; - } else { - ctrl.$setValidity('min', true); - return value; - } + return validate(ctrl, 'min', ctrl.$isEmpty(value) || value >= min, value); }; ctrl.$parsers.push(minValidator); @@ -16186,13 +16173,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { if (attr.max) { var maxValidator = function(value) { var max = parseFloat(attr.max); - if (!ctrl.$isEmpty(value) && value > max) { - ctrl.$setValidity('max', false); - return undefined; - } else { - ctrl.$setValidity('max', true); - return value; - } + return validate(ctrl, 'max', ctrl.$isEmpty(value) || value <= max, value); }; ctrl.$parsers.push(maxValidator); @@ -16200,14 +16181,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { } ctrl.$formatters.push(function(value) { - - if (ctrl.$isEmpty(value) || isNumber(value)) { - ctrl.$setValidity('number', true); - return value; - } else { - ctrl.$setValidity('number', false); - return undefined; - } + return validate(ctrl, 'number', ctrl.$isEmpty(value) || isNumber(value), value); }); } @@ -16215,13 +16189,7 @@ function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) { textInputType(scope, element, attr, ctrl, $sniffer, $browser); var urlValidator = function(value) { - if (ctrl.$isEmpty(value) || URL_REGEXP.test(value)) { - ctrl.$setValidity('url', true); - return value; - } else { - ctrl.$setValidity('url', false); - return undefined; - } + return validate(ctrl, 'url', ctrl.$isEmpty(value) || URL_REGEXP.test(value), value); }; ctrl.$formatters.push(urlValidator); @@ -16232,13 +16200,7 @@ function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) { textInputType(scope, element, attr, ctrl, $sniffer, $browser); var emailValidator = function(value) { - if (ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value)) { - ctrl.$setValidity('email', true); - return value; - } else { - ctrl.$setValidity('email', false); - return undefined; - } + return validate(ctrl, 'email', ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value), value); }; ctrl.$formatters.push(emailValidator); @@ -17842,13 +17804,13 @@ var ngControllerDirective = [function() { count: {{count}} - + it('should check ng-click', function() { - expect(binding('count')).toBe('0'); - element('.doc-example-live :button').click(); - expect(binding('count')).toBe('1'); + expect(element(by.binding('count')).getText()).toMatch('0'); + element(by.css('.doc-example-live button')).click(); + expect(element(by.binding('count')).getText()).toMatch('1'); }); - + */ /* @@ -18927,6 +18889,8 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp * | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). | * | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). | * + * Creating aliases for these properties is possible with {@link api/ng.directive:ngInit `ngInit`}. + * This may be useful when, for instance, nesting ngRepeats. * * # Special repeat start and end points * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending @@ -19809,11 +19773,9 @@ var ngSwitchWhenDirective = ngDirective({ transclude: 'element', priority: 800, require: '^ngSwitch', - compile: function(element, attrs) { - return function(scope, element, attr, ctrl, $transclude) { - ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []); - ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element }); - }; + link: function(scope, element, attrs, ctrl, $transclude) { + ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []); + ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element }); } }); @@ -19908,10 +19870,14 @@ var ngTranscludeDirective = ngDirective({ * @restrict E * * @description - * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the - * template can be used by `ngInclude`, `ngView` or directive templates. + * Load the content of a `