Commit ad89b707 authored by Randall Leeds's avatar Randall Leeds

Merge tag 'v0.3.2'

Hypothes.is 0.3.2

Conflicts:
	CHANGES.txt
parents f0b5854e 5065f4b3
/**
* @license AngularJS v1.2.22
* @license AngularJS v1.2.25
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
......
/**
* @license AngularJS v1.2.22
* @license AngularJS v1.2.25
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
......@@ -63,6 +63,8 @@ angular.mock.$Browser = function() {
return listener;
};
self.$$checkUrlChange = angular.noop;
self.cookieHash = {};
self.lastCookieHash = {};
self.deferredFns = [];
......@@ -2003,6 +2005,7 @@ if(window.jasmine || window.mocha) {
* @description
*
* *NOTE*: This function is also published on window for easy access.<br>
* *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha
*
* This function registers a module configuration code. It collects the configuration information
* which will be used when the injector is created by {@link angular.mock.inject inject}.
......@@ -2045,6 +2048,7 @@ if(window.jasmine || window.mocha) {
* @description
*
* *NOTE*: This function is also published on window for easy access.<br>
* *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha
*
* The inject function wraps a function into an injectable function. The inject() creates new
* instance of {@link auto.$injector $injector} per test, which is then used for
......
/**
* @license AngularJS v1.2.22
* @license AngularJS v1.2.25
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
......@@ -129,10 +129,16 @@ function shallowClearAndCopy(src, dst) {
* `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
* transform function or an array of such functions. The transform function takes the http
* request body and headers and returns its transformed (typically serialized) version.
* By default, transformRequest will contain one function that checks if the request data is
* an object and serializes to using `angular.toJson`. To prevent this behavior, set
* `transformRequest` to an empty array: `transformRequest: []`
* - **`transformResponse`** –
* `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
* transform function or an array of such functions. The transform function takes the http
* response body and headers and returns its transformed (typically deserialized) version.
* By default, transformResponse will contain one function that checks if the response looks like
* a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior, set
* `transformResponse` to an empty array: `transformResponse: []`
* - **`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
......
/**
* @license AngularJS v1.2.22
* @license AngularJS v1.2.25
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
......@@ -771,7 +771,6 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory);
controllerAs: 'chapter'
});
// configure html5 to get links working on jsfiddle
$locationProvider.html5Mode(true);
}])
.controller('MainCtrl', ['$route', '$routeParams', '$location',
......
/**
* @license AngularJS v1.2.22
* @license AngularJS v1.2.25
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
......@@ -597,7 +597,7 @@ angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
*/
angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
var LINKY_URL_REGEXP =
/((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/,
/((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"]/,
MAILTO_REGEXP = /^mailto:/;
return function(text, target) {
......
/**
* @license AngularJS v1.2.22
* @license AngularJS v1.2.25
* (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.22/' +
message = message + '\nhttp://errors.angularjs.org/1.2.25/' +
(module ? module + '/' : '') + code;
for (i = 2; i < arguments.length; i++) {
message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
......@@ -899,9 +899,13 @@ function copy(source, destination, stackSource, stackDest) {
}
} else {
var h = destination.$$hashKey;
forEach(destination, function(value, key) {
delete destination[key];
});
if (isArray(destination)) {
destination.length = 0;
} else {
forEach(destination, function(value, key) {
delete destination[key];
});
}
for ( var key in source) {
result = copy(source[key], null, stackSource, stackDest);
if (isObject(source[key])) {
......@@ -986,7 +990,8 @@ function equals(o1, o2) {
return true;
}
} else if (isDate(o1)) {
return isDate(o2) && o1.getTime() == o2.getTime();
if (!isDate(o2)) return false;
return (isNaN(o1.getTime()) && isNaN(o2.getTime())) || (o1.getTime() === o2.getTime());
} else if (isRegExp(o1) && isRegExp(o2)) {
return o1.toString() == o2.toString();
} else {
......@@ -1424,7 +1429,11 @@ function bootstrap(element, modules) {
if (element.injector()) {
var tag = (element[0] === document) ? 'document' : startingTag(element);
throw ngMinErr('btstrpd', "App Already Bootstrapped with this Element '{0}'", tag);
//Encode angle brackets to prevent input from being sanitized to empty string #8683
throw ngMinErr(
'btstrpd',
"App Already Bootstrapped with this Element '{0}'",
tag.replace(/</,'&lt;').replace(/>/,'&gt;'));
}
modules = modules || [];
......@@ -1688,7 +1697,7 @@ function setupModuleLoader(window) {
* @ngdoc property
* @name angular.Module#requires
* @module ng
* @returns {Array.<string>} List of module names which must be loaded before this module.
*
* @description
* Holds the list of modules which the injector will load before the current module is
* loaded.
......@@ -1699,8 +1708,9 @@ function setupModuleLoader(window) {
* @ngdoc property
* @name angular.Module#name
* @module ng
* @returns {string} Name of the module.
*
* @description
* Name of the module.
*/
name: name,
......@@ -1977,11 +1987,11 @@ function setupModuleLoader(window) {
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
*/
var version = {
full: '1.2.22', // all of these placeholder strings will be replaced by grunt's
full: '1.2.25', // all of these placeholder strings will be replaced by grunt's
major: 1, // package task
minor: 2,
dot: 22,
codeName: 'finicky-pleasure'
dot: 25,
codeName: 'hypnotic-gesticulation'
};
......@@ -4572,6 +4582,13 @@ function Browser(window, document, $log, $sniffer) {
return callback;
};
/**
* 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,
* as hashchange/popstate events fire in async.
*/
self.$$checkUrlChange = fireUrlChange;
//////////////////////////////////////////////////////////////
// Misc API
//////////////////////////////////////////////////////////////
......@@ -4788,8 +4805,10 @@ function $BrowserProvider(){
$scope.keys = [];
$scope.cache = $cacheFactory('cacheId');
$scope.put = function(key, value) {
$scope.cache.put(key, value);
$scope.keys.push(key);
if ($scope.cache.get(key) === undefined) {
$scope.keys.push(key);
}
$scope.cache.put(key, value === undefined ? null : value);
};
}]);
</file>
......@@ -5309,9 +5328,9 @@ function $TemplateCacheProvider() {
*
* * (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.
* * `^` - Locate the required controller by searching the element's parents. Throw an error if not found.
* * `?^` - Attempt to locate the required controller by searching the element's parents or pass `null` to the
* `link` fn if not found.
* * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.
* * `?^` - Attempt to locate the required controller by searching the element and its parents or pass
* `null` to the `link` fn if not found.
*
*
* #### `controllerAs`
......@@ -7129,8 +7148,10 @@ function directiveNormalize(name) {
/**
* @ngdoc property
* @name $compile.directive.Attributes#$attr
* @returns {object} A map of DOM element attribute names to the normalized name. This is
* needed to do reverse lookup from normalized name back to actual name.
*
* @description
* A map of DOM element attribute names to the normalized name. This is
* needed to do reverse lookup from normalized name back to actual name.
*/
......@@ -7885,7 +7906,7 @@ function $HttpProvider() {
* that only JavaScript running on your domain could have sent the request. The token must be
* unique for each user and must be verifiable by the server (to prevent the JavaScript from
* making up its own tokens). We recommend that the token is a digest of your site's
* authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography))
* authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)
* for added security.
*
* The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
......@@ -8393,7 +8414,7 @@ function $HttpProvider() {
if (isObject(v)) {
if (isDate(v)){
v = v.toISOString();
} else if (isObject(v)) {
} else {
v = toJson(v);
}
}
......@@ -8843,7 +8864,7 @@ function $InterpolateProvider() {
* @description
* Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
*
* Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change
* Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change
* the symbol.
*
* @returns {string} start symbol.
......@@ -8859,7 +8880,7 @@ function $InterpolateProvider() {
* @description
* Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
*
* Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change
* Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change
* the symbol.
*
* @returns {string} end symbol.
......@@ -8951,7 +8972,7 @@ function $IntervalProvider() {
* };
*
* $scope.$on('$destroy', function() {
* // Make sure that the interval nis destroyed too
* // Make sure that the interval is destroyed too
* $scope.stopFight();
* });
* }])
......@@ -9449,17 +9470,16 @@ LocationHashbangInHtml5Url.prototype =
* Change path, search and hash, when called with parameter and return `$location`.
*
* @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
* @param {string=} replace The path that will be changed
* @return {string} url
*/
url: function(url, replace) {
url: function(url) {
if (isUndefined(url))
return this.$$url;
var match = PATH_MATCH.exec(url);
if (match[1]) this.path(decodeURIComponent(match[1]));
if (match[2] || match[1]) this.search(match[3] || '');
this.hash(match[5] || '', replace);
this.hash(match[5] || '');
return this;
},
......@@ -9517,10 +9537,11 @@ LocationHashbangInHtml5Url.prototype =
* Note: Path should always begin with forward slash (/), this method will add the forward slash
* if it is missing.
*
* @param {string=} path New path
* @param {(string|number)=} path New path
* @return {string} path
*/
path: locationGetterSetter('$$path', function(path) {
path = path ? path.toString() : '';
return path.charAt(0) == '/' ? path : '/' + path;
}),
......@@ -9556,7 +9577,7 @@ LocationHashbangInHtml5Url.prototype =
* If the argument is a hash object containing an array of values, these values will be encoded
* as duplicate search parameters in the url.
*
* @param {(string|Array<string>|boolean)=} paramValue If `search` is a string, then `paramValue`
* @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`
* will override only a single search property.
*
* If `paramValue` is an array, it will override the property of the `search` component of
......@@ -9575,7 +9596,8 @@ LocationHashbangInHtml5Url.prototype =
case 0:
return this.$$search;
case 1:
if (isString(search)) {
if (isString(search) || isNumber(search)) {
search = search.toString();
this.$$search = parseKeyValue(search);
} else if (isObject(search)) {
// remove object undefined or null properties
......@@ -9612,10 +9634,12 @@ LocationHashbangInHtml5Url.prototype =
*
* Change hash fragment when called with parameter and return `$location`.
*
* @param {string=} hash New hash fragment
* @param {(string|number)=} hash New hash fragment
* @return {string} hash
*/
hash: locationGetterSetter('$$hash', identity),
hash: locationGetterSetter('$$hash', function(hash) {
return hash ? hash.toString() : '';
}),
/**
* @ngdoc method
......@@ -9799,7 +9823,7 @@ function $LocationProvider(){
// http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx
var href = elm.attr('href') || elm.attr('xlink:href');
if (href.indexOf('://') < 0) { // Ignore absolute URLs
if (href && href.indexOf('://') < 0) { // Ignore absolute URLs
var prefix = '#' + hashPrefix;
if (href[0] == '/') {
// absolute path - replace old path
......@@ -9811,6 +9835,7 @@ function $LocationProvider(){
// relative path - join with current path
var stack = $location.path().split("/"),
parts = href.split("/");
if (stack.length === 2 && !stack[1]) stack.length = 1;
for (var i=0; i<parts.length; i++) {
if (parts[i] == ".")
continue;
......@@ -10809,7 +10834,7 @@ Parser.prototype = {
var context = contextGetter ? contextGetter(scope, locals) : scope;
for (var i = 0; i < argsFn.length; i++) {
args.push(argsFn[i](scope, locals));
args.push(ensureSafeObject(argsFn[i](scope, locals), parser.text));
}
var fnPtr = fn(scope, locals, context) || noop;
......@@ -10897,13 +10922,15 @@ Parser.prototype = {
//////////////////////////////////////////////////
function setter(obj, path, setValue, fullExp, options) {
ensureSafeObject(obj, fullExp);
//needed?
options = options || {};
var element = path.split('.'), key;
for (var i = 0; element.length > 1; i++) {
key = ensureSafeMemberName(element.shift(), fullExp);
var propertyObj = obj[key];
var propertyObj = ensureSafeObject(obj[key], fullExp);
if (!propertyObj) {
propertyObj = {};
obj[key] = propertyObj;
......@@ -10923,7 +10950,6 @@ function setter(obj, path, setValue, fullExp, options) {
}
}
key = ensureSafeMemberName(element.shift(), fullExp);
ensureSafeObject(obj, fullExp);
ensureSafeObject(obj[key], fullExp);
obj[key] = setValue;
return setValue;
......@@ -11987,10 +12013,26 @@ function $RootScopeProvider(){
/**
* @ngdoc property
* @name $rootScope.Scope#$id
* @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for
* debugging.
*
* @description
* Unique scope ID (monotonically increasing) useful for debugging.
*/
/**
* @ngdoc property
* @name $rootScope.Scope#$parent
*
* @description
* Reference to the parent scope.
*/
/**
* @ngdoc property
* @name $rootScope.Scope#$root
*
* @description
* Reference to the root scope.
*/
Scope.prototype = {
constructor: Scope,
......@@ -12002,9 +12044,8 @@ function $RootScopeProvider(){
* @description
* Creates a new child {@link ng.$rootScope.Scope scope}.
*
* The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and
* {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the
* scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
* The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.
* The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
*
* {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is
* desired for the scope and its child scopes to be permanently detached from the parent and
......@@ -12457,6 +12498,8 @@ function $RootScopeProvider(){
logIdx, logMsg, asyncTask;
beginPhase('$digest');
// Check for changes to browser url that happened in sync before the call to $digest
$browser.$$checkUrlChange();
lastDirtyWatch = null;
......@@ -13003,7 +13046,7 @@ function $RootScopeProvider(){
*/
function $$SanitizeUriProvider() {
var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/,
imgSrcSanitizationWhitelist = /^\s*(https?|ftp|file):|data:image\//;
imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file):|data:image\/)/;
/**
* @description
......@@ -14510,16 +14553,6 @@ function $WindowProvider(){
* For more information about how angular filters work, and how to create your own filters, see
* {@link guide/filter Filters} in the Angular Developer Guide.
*/
/**
* @ngdoc method
* @name $filterProvider#register
* @description
* Register filter factory function.
*
* @param {String} name Name of the filter.
* @param {Function} fn The filter factory function which is injectable.
*/
/**
* @ngdoc service
......@@ -14558,7 +14591,7 @@ function $FilterProvider($provide) {
/**
* @ngdoc method
* @name $controllerProvider#register
* @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.
* @returns {Object} Registered filter instance, or if a map of filters was provided then a map
......@@ -14631,7 +14664,9 @@ function $FilterProvider($provide) {
* which have property `name` containing "M" and property `phone` containing "1". A special
* property name `$` can be used (as in `{$:"text"}`) to accept a match against any
* property of the object. That's equivalent to the simple substring match with a `string`
* as described above.
* as described above. The predicate can be negated by prefixing the string with `!`.
* For Example `{name: "!M"}` predicate will return an array of items which have property `name`
* not containing "M".
*
* - `function(value)`: A predicate function can be used to write arbitrary filters. The function is
* called for each element of `array`. The final result is an array of those elements that
......@@ -14980,6 +15015,10 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
if (number === 0) {
isNegative = false;
}
var fraction = ('' + number).split(DECIMAL_SEP);
var whole = fraction[0];
fraction = fraction[1] || '';
......@@ -15149,8 +15188,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
* * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)
* * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)
*
* `format` string can contain literal values. These need to be quoted with single quotes (e.g.
* `"h 'in the morning'"`). In order to output single quote, use two single quotes in a sequence
* `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.
* `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence
* (e.g. `"h 'o''clock'"`).
*
* @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
......@@ -15170,6 +15209,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
<span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>
<span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
<span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>
<span ng-non-bindable>{{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}</span>:
<span>{{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}</span><br>
</file>
<file name="protractor.js" type="protractor">
it('should format date', function() {
......@@ -15179,6 +15220,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()).
toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()).
toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/);
});
</file>
</example>
......@@ -15443,9 +15486,13 @@ function limitToFilter(){
*
* - `function`: Getter function. The result of this function will be sorted using the
* `<`, `=`, `>` operator.
* - `string`: An Angular expression which evaluates to an object to order by, such as 'name'
* to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control
* ascending or descending sort order (for example, +name or -name).
* - `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
* is interpreted as a property name to be used in comparisons (for example `"special name"`
* to sort object by the value of their `special name` property). An expression can be
* optionally prefixed with `+` or `-` to control ascending or descending sort order
* (for example, `+name` or `-name`).
* - `Array`: An array of function or string predicates. The first predicate in the array
* is used for sorting, but when two items are equivalent, the next predicate is used.
*
......@@ -15536,7 +15583,7 @@ function limitToFilter(){
orderByFilter.$inject = ['$parse'];
function orderByFilter($parse){
return function(array, sortPredicate, reverseOrder) {
if (!isArray(array)) return array;
if (!(isArrayLike(array))) return array;
if (!sortPredicate) return array;
sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
sortPredicate = map(sortPredicate, function(predicate){
......@@ -15813,7 +15860,7 @@ var htmlAnchorDirective = valueFn({
*
* @description
*
* The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:
* We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:
* ```html
* <div ng-init="scope = { isDisabled: false }">
* <button disabled="{{scope.isDisabled}}">Disabled</button>
......@@ -16033,8 +16080,12 @@ forEach(['src', 'srcset', 'href'], function(attrName) {
}
attr.$observe(normalized, function(value) {
if (!value)
return;
if (!value) {
if (attrName === 'href') {
attr.$set(name, null);
}
return;
}
attr.$set(name, value);
......@@ -16119,8 +16170,9 @@ function FormController(element, attrs, $scope, $animate) {
// convenience method for easy toggling of classes
function toggleValidCss(isValid, validationErrorKey) {
validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
$animate.removeClass(element, (isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey);
$animate.addClass(element, (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
$animate.setClass(element,
(isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey,
(isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey);
}
/**
......@@ -16335,8 +16387,6 @@ function FormController(element, attrs, $scope, $animate) {
* hitting enter in any of the input fields will trigger the click handler on the *first* button or
* input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)
*
* @param {string=} name Name of the form. If specified, the form controller will be published into
* related scope, under this name.
*
* ## Animation Hooks
*
......@@ -16414,6 +16464,8 @@ function FormController(element, attrs, $scope, $animate) {
</file>
</example>
*
* @param {string=} name Name of the form. If specified, the form controller will be published into
* related scope, under this name.
*/
var formDirectiveFactory = function(isNgForm) {
return ['$timeout', function($timeout) {
......@@ -16492,7 +16544,9 @@ var inputType = {
* @name input[text]
*
* @description
* Standard HTML text input with angular data binding.
* Standard HTML text input with angular data binding, inherited by most of the `input` elements.
*
* *NOTE* Not every feature offered is available for all input types.
*
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} name Property name of the form under which the control is published.
......@@ -16510,6 +16564,8 @@ var inputType = {
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
* @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
* This parameter is ignored for input[type=password] controls, which will never trim the
* input.
*
* @example
<example name="text-input-directive" module="textInputExample">
......@@ -16949,6 +17005,7 @@ function addNativeHtml5Validators(ctrl, validatorName, badFlags, ignoreFlags, va
function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
var validity = element.prop(VALIDITY_STATE_PROPERTY);
var placeholder = element[0].placeholder, noevent = {};
var type = lowercase(element[0].type);
ctrl.$$validityState = validity;
// In composition mode, users are still inputing intermediate text buffer,
......@@ -16982,8 +17039,8 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
// By default we will trim the value
// If the attribute ng-trim exists we will avoid trimming
// e.g. <input ng-model="foo" ng-trim="false">
if (toBoolean(attr.ngTrim || 'T')) {
// If input type is 'password', the value is never trimmed
if (type !== 'password' && (toBoolean(attr.ngTrim || 'T'))) {
value = trim(value);
}
......@@ -16992,7 +17049,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
// a row.
var revalidate = validity && ctrl.$$hasNativeValidators;
if (ctrl.$viewValue !== value || (value === '' && revalidate)) {
if (scope.$$phase) {
if (scope.$root.$$phase) {
ctrl.$setViewValue(value);
} else {
scope.$apply(function() {
......@@ -17258,6 +17315,8 @@ function checkboxInputType(scope, element, attr, ctrl) {
* HTML input element control with angular data-binding. Input control follows HTML5 input types
* and polyfills the HTML5 validation behavior for older browsers.
*
* *NOTE* Not every feature offered is available for all input types.
*
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} name Property name of the form under which the control is published.
* @param {string=} required Sets `required` validation error key if the value is not entered.
......@@ -17271,6 +17330,9 @@ function checkboxInputType(scope, element, attr, ctrl) {
* patterns defined as scope expressions.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
* @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
* This parameter is ignored for input[type=password] controls, which will never trim the
* input.
*
* @example
<example name="input-directive" module="inputExample">
......@@ -18260,7 +18322,6 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
* @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
*
* @example
Try it here: enter text in text box and watch the greeting change.
<example module="bindHtmlExample" deps="angular-sanitize.js">
<file name="index.html">
......@@ -19030,7 +19091,9 @@ var ngControllerDirective = [function() {
<button ng-click="count = count + 1" ng-init="count=0">
Increment
</button>
count: {{count}}
<span>
count: {{count}}
<span>
</file>
<file name="protractor.js" type="protractor">
it('should check ng-click', function() {
......@@ -19048,19 +19111,32 @@ var ngControllerDirective = [function() {
* Events that are handled via these handler are always configured not to propagate further.
*/
var ngEventDirectives = {};
// For events that might fire synchronously during DOM manipulation
// we need to execute their event handlers asynchronously using $evalAsync,
// so that they are not executed in an inconsistent state.
var forceAsyncEvents = {
'blur': true,
'focus': true
};
forEach(
'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
function(name) {
var directiveName = directiveNormalize('ng-' + name);
ngEventDirectives[directiveName] = ['$parse', function($parse) {
function(eventName) {
var directiveName = directiveNormalize('ng-' + eventName);
ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {
return {
compile: function($element, attr) {
var fn = $parse(attr[directiveName]);
return function ngEventHandler(scope, element) {
element.on(lowercase(name), function(event) {
scope.$apply(function() {
element.on(eventName, function(event) {
var callback = function() {
fn(scope, {$event:event});
});
};
if (forceAsyncEvents[eventName] && $rootScope.$$phase) {
scope.$evalAsync(callback);
} else {
scope.$apply(callback);
}
});
};
}
......@@ -19377,6 +19453,10 @@ forEach(
* @description
* Specify custom behavior on focus event.
*
* Note: As the `focus` event is executed synchronously when calling `input.focus()`
* AngularJS executes the expression using `scope.$evalAsync` if the event is fired
* during an `$apply` to ensure a consistent state.
*
* @element window, input, select, textarea, a
* @priority 0
* @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon
......@@ -19393,6 +19473,14 @@ forEach(
* @description
* Specify custom behavior on blur event.
*
* A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when
* an element has lost focus.
*
* Note: As the `blur` event is executed synchronously also during DOM manipulations
* (e.g. removing a focussed input),
* AngularJS executes the expression using `scope.$evalAsync` if the event is fired
* during an `$apply` to ensure a consistent state.
*
* @element window, input, select, textarea, a
* @priority 0
* @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon
......@@ -20473,8 +20561,9 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
if (block && block.scope) lastBlockMap[block.id] = block;
});
// This is a duplicate and we need to throw an error
throw ngRepeatMinErr('dupes', "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}",
expression, trackById);
throw ngRepeatMinErr('dupes',
"Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}",
expression, trackById, toJson(value));
} else {
// new never before seen block
nextBlockOrder[index] = { id: trackById };
......@@ -20565,8 +20654,8 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
*
* @description
* The `ngShow` directive shows or hides the given HTML element based on the expression
* provided to the ngShow attribute. The element is shown or hidden by removing or adding
* the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
* provided to the `ngShow` attribute. The element is shown or hidden by removing or adding
* the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
* in AngularJS and sets the display style to none (using an !important flag).
* For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
*
......@@ -20578,8 +20667,8 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
* <div ng-show="myValue" class="ng-hide"></div>
* ```
*
* When the ngShow expression evaluates to false then the ng-hide CSS class is added to the class attribute
* on the element causing it to become hidden. When true, the ng-hide CSS class is removed
* When the `ngShow` expression evaluates to false then the `.ng-hide` CSS class is added to the class attribute
* on the element causing it to become hidden. When true, the `.ng-hide` CSS class is removed
* from the element causing the element not to appear hidden.
*
* <div class="alert alert-warning">
......@@ -20589,7 +20678,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
*
* ## Why is !important used?
*
* You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
* You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
* can be easily overridden by heavier selectors. For example, something as simple
* as changing the display style on a HTML list item would make hidden elements appear visible.
* This also becomes a bigger issue when dealing with CSS frameworks.
......@@ -20598,7 +20687,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
* specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
* styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
*
* ### Overriding .ng-hide
* ### Overriding `.ng-hide`
*
* By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change
* the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
......@@ -20616,7 +20705,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
*
* By default you don't need to override in CSS anything and the animations will work around the display style.
*
* ## A note about animations with ngShow
* ## A note about animations with `ngShow`
*
* Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
* is true and false. This system works like the animation system present with ngClass except that
......@@ -20641,8 +20730,8 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
* property to block during animation states--ngAnimate will handle the style toggling automatically for you.
*
* @animations
* addClass: .ng-hide - happens after the ngShow expression evaluates to a truthy value and the just before contents are set to visible
* removeClass: .ng-hide - happens after the ngShow expression evaluates to a non truthy value and just before the contents are set to hidden
* addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible
* removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden
*
* @element ANY
* @param {expression} ngShow If the {@link guide/expression expression} is truthy
......@@ -20722,7 +20811,7 @@ var ngShowDirective = ['$animate', function($animate) {
*
* @description
* The `ngHide` directive shows or hides the given HTML element based on the expression
* provided to the ngHide attribute. The element is shown or hidden by removing or adding
* provided to the `ngHide` attribute. The element is shown or hidden by removing or adding
* the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
* in AngularJS and sets the display style to none (using an !important flag).
* For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
......@@ -20735,8 +20824,8 @@ var ngShowDirective = ['$animate', function($animate) {
* <div ng-hide="myValue"></div>
* ```
*
* When the ngHide expression evaluates to true then the .ng-hide CSS class is added to the class attribute
* on the element causing it to become hidden. When false, the ng-hide CSS class is removed
* When the `.ngHide` expression evaluates to true then the `.ng-hide` CSS class is added to the class attribute
* on the element causing it to become hidden. When false, the `.ng-hide` CSS class is removed
* from the element causing the element not to appear hidden.
*
* <div class="alert alert-warning">
......@@ -20746,7 +20835,7 @@ var ngShowDirective = ['$animate', function($animate) {
*
* ## Why is !important used?
*
* You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
* You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
* can be easily overridden by heavier selectors. For example, something as simple
* as changing the display style on a HTML list item would make hidden elements appear visible.
* This also becomes a bigger issue when dealing with CSS frameworks.
......@@ -20755,7 +20844,7 @@ var ngShowDirective = ['$animate', function($animate) {
* specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
* styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
*
* ### Overriding .ng-hide
* ### Overriding `.ng-hide`
*
* By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change
* the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
......@@ -20773,7 +20862,7 @@ var ngShowDirective = ['$animate', function($animate) {
*
* By default you don't need to override in CSS anything and the animations will work around the display style.
*
* ## A note about animations with ngHide
* ## A note about animations with `ngHide`
*
* Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
* is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`
......@@ -20797,8 +20886,8 @@ var ngShowDirective = ['$animate', function($animate) {
* property to block during animation states--ngAnimate will handle the style toggling automatically for you.
*
* @animations
* removeClass: .ng-hide - happens after the ngHide expression evaluates to a truthy value and just before the contents are set to hidden
* addClass: .ng-hide - happens after the ngHide expression evaluates to a non truthy value and just before the contents are set to visible
* removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden
* addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible
*
* @element ANY
* @param {expression} ngHide If the {@link guide/expression expression} is truthy then
......@@ -21651,6 +21740,19 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
ctrl.$render = render;
scope.$watchCollection(valuesFn, render);
scope.$watchCollection(function () {
var locals = {},
values = valuesFn(scope);
if (values) {
var toDisplay = new Array(values.length);
for (var i = 0, ii = values.length; i < ii; i++) {
locals[valueName] = values[i];
toDisplay[i] = displayFn(scope, locals);
}
return toDisplay;
}
}, render);
if ( multiple ) {
scope.$watchCollection(function() { return ctrl.$modelValue; }, render);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment