vendor/assets/javascripts/unstable/angular-scenario.js in angularjs-rails-1.3.2 vs vendor/assets/javascripts/unstable/angular-scenario.js in angularjs-rails-1.3.3
- old
+ new
@@ -9188,11 +9188,11 @@
return jQuery;
}));
/**
- * @license AngularJS v1.3.2
+ * @license AngularJS v1.3.3
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, document){
var _jQuery = window.jQuery.noConflict(true);
@@ -9232,44 +9232,27 @@
return function() {
var code = arguments[0],
prefix = '[' + (module ? module + ':' : '') + code + '] ',
template = arguments[1],
templateArgs = arguments,
- stringify = function(obj) {
- if (typeof obj === 'function') {
- return obj.toString().replace(/ \{[\s\S]*$/, '');
- } else if (typeof obj === 'undefined') {
- return 'undefined';
- } else if (typeof obj !== 'string') {
- return JSON.stringify(obj);
- }
- return obj;
- },
+
message, i;
message = prefix + template.replace(/\{\d+\}/g, function(match) {
var index = +match.slice(1, -1), arg;
if (index + 2 < templateArgs.length) {
- arg = templateArgs[index + 2];
- if (typeof arg === 'function') {
- return arg.toString().replace(/ ?\{[\s\S]*$/, '');
- } else if (typeof arg === 'undefined') {
- return 'undefined';
- } else if (typeof arg !== 'string') {
- return toJson(arg);
- }
- return arg;
+ return toDebugString(templateArgs[index + 2]);
}
return match;
});
- message = message + '\nhttp://errors.angularjs.org/1.3.2/' +
+ message = message + '\nhttp://errors.angularjs.org/1.3.3/' +
(module ? module + '/' : '') + code;
for (i = 2; i < arguments.length; i++) {
- message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
- encodeURIComponent(stringify(arguments[i]));
+ message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
+ encodeURIComponent(toDebugString(arguments[i]));
}
return new ErrorConstructor(message);
};
}
@@ -9905,11 +9888,11 @@
return Array.prototype.indexOf.call(array, obj) != -1;
}
function arrayRemove(array, value) {
var index = array.indexOf(value);
- if (index >=0)
+ if (index >= 0)
array.splice(index, 1);
return value;
}
/**
@@ -10106,11 +10089,11 @@
if (t1 == t2) {
if (t1 == 'object') {
if (isArray(o1)) {
if (!isArray(o2)) return false;
if ((length = o1.length) == o2.length) {
- for (key=0; key<length; key++) {
+ for (key = 0; key < length; key++) {
if (!equals(o1[key], o2[key])) return false;
}
return true;
}
} else if (isDate(o1)) {
@@ -10192,11 +10175,11 @@
var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
if (isFunction(fn) && !(fn instanceof RegExp)) {
return curryArgs.length
? function() {
return arguments.length
- ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))
+ ? fn.apply(self, concat(curryArgs, arguments, 0))
: fn.apply(self, curryArgs);
}
: function() {
return arguments.length
? fn.apply(self, arguments)
@@ -10392,11 +10375,11 @@
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) {
+ for (i = 0; i < ii; ++i) {
attr = ngAttrPrefixes[i] + ngAttr;
if (isString(attr = element.attr(attr))) {
return attr;
}
}
@@ -11177,10 +11160,38 @@
};
});
}
+/* global: toDebugString: true */
+
+function serializeObject(obj) {
+ var seen = [];
+
+ return JSON.stringify(obj, function(key, val) {
+ val = toJsonReplacer(key, val);
+ if (isObject(val)) {
+
+ if (seen.indexOf(val) >= 0) return '<<already seen>>';
+
+ seen.push(val);
+ }
+ return val;
+ });
+}
+
+function toDebugString(obj) {
+ if (typeof obj === 'function') {
+ return obj.toString().replace(/ \{[\s\S]*$/, '');
+ } else if (typeof obj === 'undefined') {
+ return 'undefined';
+ } else if (typeof obj !== 'string') {
+ return serializeObject(obj);
+ }
+ return obj;
+}
+
/* global angularModule: true,
version: true,
$LocaleProvider,
$CompileProvider,
@@ -11279,15 +11290,15 @@
* - `minor` – `{number}` – Minor version number, such as "9".
* - `dot` – `{number}` – Dot version number, such as "18".
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
*/
var version = {
- full: '1.3.2', // all of these placeholder strings will be replaced by grunt's
+ full: '1.3.3', // all of these placeholder strings will be replaced by grunt's
major: 1, // package task
minor: 3,
- dot: 2,
- codeName: 'cardiovasculatory-magnification'
+ dot: 3,
+ codeName: 'undersea-arithmetic'
};
function publishExternalAPI(angular) {
extend(angular, {
@@ -12016,11 +12027,11 @@
element[name] = false;
element.removeAttribute(lowercasedName);
}
} else {
return (element[name] ||
- (element.attributes.getNamedItem(name)|| noop).specified)
+ (element.attributes.getNamedItem(name) || noop).specified)
? lowercasedName
: undefined;
}
} else if (isDefined(value)) {
element.setAttribute(name, value);
@@ -13352,11 +13363,11 @@
/**
* @ngdoc method
* @name $anchorScrollProvider#disableAutoScrolling
*
* @description
- * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically will detect changes to
+ * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to
* {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />
* Use this method to disable automatic scrolling.
*
* If automatic scrolling is disabled, one must explicitly call
* {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the
@@ -14001,12 +14012,11 @@
* the real browser apis.
*/
/**
* @param {object} window The global window object.
* @param {object} document jQuery wrapped document.
- * @param {function()} XHR XMLHttpRequest constructor.
- * @param {object} $log console.log or an object with the same interface.
+ * @param {object} $log window.console or an object with the same interface.
* @param {object} $sniffer $sniffer service
*/
function Browser(window, document, $log, $sniffer) {
var self = this,
rawDocument = document[0],
@@ -14352,12 +14362,12 @@
// 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 ("+
+ $log.warn("Cookie '" + name +
+ "' possibly not set or overflowed because it was too large (" +
cookieLength + " > 4096 bytes)!");
}
}
}
} else {
@@ -15018,11 +15028,11 @@
* For example, if the expression is `increment(amount)` then we can specify the amount value
* by calling the `localFn` as `localFn({amount: 22})`.
*
*
* #### `bindToController`
- * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController` will
+ * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will
* allow a component to have its properties bound to the controller, rather than to scope. When the controller
* is instantiated, the initial values of the isolate scope bindings are already available.
*
* #### `controller`
* Controller constructor function. The controller is instantiated before the
@@ -15867,20 +15877,20 @@
// split srcset into tuple of uri and descriptor except for the last item
var rawUris = trimmedSrcset.split(pattern);
// for each tuples
var nbrUrisWith2parts = Math.floor(rawUris.length / 2);
- for (var i=0; i<nbrUrisWith2parts; i++) {
- var innerIdx = i*2;
+ for (var i = 0; i < nbrUrisWith2parts; i++) {
+ var innerIdx = i * 2;
// sanitize the uri
result += $$sanitizeUri(trim(rawUris[innerIdx]), true);
// add the descriptor
- result += (" " + trim(rawUris[innerIdx+1]));
+ result += (" " + trim(rawUris[innerIdx + 1]));
}
// split the last item into uri and descriptor
- var lastTuple = trim(rawUris[i*2]).split(/\s/);
+ var lastTuple = trim(rawUris[i * 2]).split(/\s/);
// sanitize the last uri
result += $$sanitizeUri(trim(lastTuple[0]), true);
// and add the last descriptor if any
@@ -16070,11 +16080,11 @@
// TODO: Make this detect MathML as well...
var node = parentElement && parentElement[0];
if (!node) {
return 'html';
} else {
- return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg': 'html';
+ return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html';
}
}
/**
* Compile function matches each node in nodeList against the directives. Once all directives
@@ -16883,11 +16893,11 @@
endAttrName) {
if (name === ignoreDirective) return null;
var match = null;
if (hasDirectives.hasOwnProperty(name)) {
for (var directive, directives = $injector.get(name + Suffix),
- i = 0, ii = directives.length; i<ii; i++) {
+ i = 0, ii = directives.length; i < ii; i++) {
try {
directive = directives[i];
if ((maxPriority === undefined || maxPriority > directive.priority) &&
directive.restrict.indexOf(location) != -1) {
if (startAttrName) {
@@ -16912,11 +16922,11 @@
* @returns true if directive was registered as multi-element.
*/
function directiveIsMultiElement(name) {
if (hasDirectives.hasOwnProperty(name)) {
for (var directive, directives = $injector.get(name + Suffix),
- i = 0, ii = directives.length; i<ii; i++) {
+ i = 0, ii = directives.length; i < ii; i++) {
directive = directives[i];
if (directive.multiElement) {
return true;
}
}
@@ -17131,11 +17141,11 @@
type = lowercase(type || 'html');
switch (type) {
case 'svg':
case 'math':
var wrapper = document.createElement('div');
- wrapper.innerHTML = '<'+type+'>'+template+'</'+type+'>';
+ wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>';
return wrapper.childNodes[0].childNodes;
default:
return template;
}
}
@@ -17488,10 +17498,14 @@
* * 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.
* @return {Object} Instance of given controller.
*
* @description
* `$controller` service is responsible for instantiating controllers.
@@ -17662,11 +17676,11 @@
function defaultHttpResponseTransform(data, headers) {
if (isString(data)) {
// strip json vulnerability protection prefix
data = data.replace(JSON_PROTECTION_PREFIX, '');
var contentType = headers('Content-Type');
- if ((contentType && contentType.indexOf(APPLICATION_JSON) === 0) ||
+ if ((contentType && contentType.indexOf(APPLICATION_JSON) === 0 && data.trim()) ||
(JSON_START.test(data) && JSON_END.test(data))) {
data = fromJson(data);
}
}
return data;
@@ -19233,11 +19247,12 @@
replace(escapedEndRegexp, endSymbol);
}
function parseStringifyInterceptor(value) {
try {
- return stringify(getValue(value));
+ 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);
}
@@ -19557,25 +19572,25 @@
}
return segments.join('/');
}
-function parseAbsoluteUrl(absoluteUrl, locationObj, appBase) {
- var parsedUrl = urlResolve(absoluteUrl, appBase);
+function parseAbsoluteUrl(absoluteUrl, locationObj) {
+ var parsedUrl = urlResolve(absoluteUrl);
locationObj.$$protocol = parsedUrl.protocol;
locationObj.$$host = parsedUrl.hostname;
locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
}
-function parseAppUrl(relativeUrl, locationObj, appBase) {
+function parseAppUrl(relativeUrl, locationObj) {
var prefixed = (relativeUrl.charAt(0) !== '/');
if (prefixed) {
relativeUrl = '/' + relativeUrl;
}
- var match = urlResolve(relativeUrl, appBase);
+ var match = urlResolve(relativeUrl);
locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
match.pathname.substring(1) : match.pathname);
locationObj.$$search = parseKeyValue(match.search);
locationObj.$$hash = decodeURIComponent(match.hash);
@@ -19626,11 +19641,11 @@
*/
function LocationHtml5Url(appBase, basePrefix) {
this.$$html5 = true;
basePrefix = basePrefix || '';
var appBaseNoFile = stripFile(appBase);
- parseAbsoluteUrl(appBase, this, appBase);
+ parseAbsoluteUrl(appBase, this);
/**
* Parse given html5 (regular) url string into properties
* @param {string} url HTML5 url
@@ -19641,11 +19656,11 @@
if (!isString(pathUrl)) {
throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
appBaseNoFile);
}
- parseAppUrl(pathUrl, this, appBase);
+ parseAppUrl(pathUrl, this);
if (!this.$$path) {
this.$$path = '/';
}
@@ -19704,11 +19719,11 @@
* @param {string} hashPrefix hashbang prefix
*/
function LocationHashbangUrl(appBase, hashPrefix) {
var appBaseNoFile = stripFile(appBase);
- parseAbsoluteUrl(appBase, this, appBase);
+ parseAbsoluteUrl(appBase, this);
/**
* Parse given hashbang url into properties
* @param {string} url Hashbang url
@@ -19724,11 +19739,11 @@
if (!isString(withoutHashUrl)) {
throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url,
hashPrefix);
}
- parseAppUrl(withoutHashUrl, this, appBase);
+ parseAppUrl(withoutHashUrl, this);
this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
this.$$compose();
@@ -20364,15 +20379,23 @@
// update $location when $browser url changes
$browser.onUrlChange(function(newUrl, newState) {
$rootScope.$evalAsync(function() {
var oldUrl = $location.absUrl();
var oldState = $location.$$state;
+ var defaultPrevented;
$location.$$parse(newUrl);
$location.$$state = newState;
- if ($rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
- newState, oldState).defaultPrevented) {
+
+ defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
+ newState, oldState).defaultPrevented;
+
+ // if the location was changed by a `$locationChangeStart` handler then stop
+ // processing this location change
+ if ($location.absUrl() !== newUrl) return;
+
+ if (defaultPrevented) {
$location.$$parse(oldUrl);
$location.$$state = oldState;
setBrowserUrlWithFallback(oldUrl, false, oldState);
} else {
initializing = false;
@@ -20392,17 +20415,24 @@
if (initializing || urlOrStateChanged) {
initializing = false;
$rootScope.$evalAsync(function() {
- if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl,
- $location.$$state, oldState).defaultPrevented) {
+ var newUrl = $location.absUrl();
+ var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
+ $location.$$state, oldState).defaultPrevented;
+
+ // if the location was changed by a `$locationChangeStart` handler then stop
+ // processing this location change
+ if ($location.absUrl() !== newUrl) return;
+
+ if (defaultPrevented) {
$location.$$parse(oldUrl);
$location.$$state = oldState;
} else {
if (urlOrStateChanged) {
- setBrowserUrlWithFallback($location.absUrl(), currentReplace,
+ setBrowserUrlWithFallback(newUrl, currentReplace,
oldState === $location.$$state ? null : $location.$$state);
}
afterLocationChange(oldUrl, oldState);
}
});
@@ -20588,36 +20618,38 @@
var $parseMinErr = minErr('$parse');
// Sandboxing Angular Expressions
// ------------------------------
// Angular expressions are generally considered safe because these expressions only have direct
-// access to $scope and locals. However, one can obtain the ability to execute arbitrary JS code by
+// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by
// obtaining a reference to native JS functions such as the Function constructor.
//
// As an example, consider the following Angular expression:
//
// {}.toString.constructor('alert("evil JS code")')
//
// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
// against the expression language, but not to prevent exploits that were enabled by exposing
-// sensitive JavaScript or browser apis on Scope. Exposing such objects on a Scope is never a good
+// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good
// practice and therefore we are not even trying to protect against interaction with an object
// explicitly exposed in this way.
//
// In general, it is not possible to access a Window object from an angular expression unless a
// window or some DOM object that has a reference to window is published onto a Scope.
// Similarly we prevent invocations of function known to be dangerous, as well as assignments to
// native objects.
+//
+// See https://docs.angularjs.org/guide/security
function ensureSafeMemberName(name, fullExpression) {
if (name === "__defineGetter__" || name === "__defineSetter__"
|| name === "__lookupGetter__" || name === "__lookupSetter__"
|| name === "__proto__") {
throw $parseMinErr('isecfld',
'Attempting to access a disallowed field in Angular expressions! '
- +'Expression: {0}', fullExpression);
+ + 'Expression: {0}', fullExpression);
}
return name;
}
function ensureSafeObject(obj, fullExpression) {
@@ -20690,28 +20722,28 @@
if (isDefined(b)) {
return a + b;
}
return a;
}
- return isDefined(b)?b:undefined;},
+ return isDefined(b) ? b : undefined;},
'-':function(self, locals, a, b) {
a=a(self, locals); b=b(self, locals);
- return (isDefined(a)?a:0)-(isDefined(b)?b:0);
+ return (isDefined(a) ? a : 0) - (isDefined(b) ? b : 0);
},
- '*':function(self, locals, a, b) {return a(self, locals)*b(self, locals);},
- '/':function(self, locals, a, b) {return a(self, locals)/b(self, locals);},
- '%':function(self, locals, a, b) {return a(self, locals)%b(self, locals);},
- '===':function(self, locals, a, b) {return a(self, locals)===b(self, locals);},
- '!==':function(self, locals, a, b) {return a(self, locals)!==b(self, locals);},
- '==':function(self, locals, a, b) {return a(self, locals)==b(self, locals);},
- '!=':function(self, locals, a, b) {return a(self, locals)!=b(self, locals);},
- '<':function(self, locals, a, b) {return a(self, locals)<b(self, locals);},
- '>':function(self, locals, a, b) {return a(self, locals)>b(self, locals);},
- '<=':function(self, locals, a, b) {return a(self, locals)<=b(self, locals);},
- '>=':function(self, locals, a, b) {return a(self, locals)>=b(self, locals);},
- '&&':function(self, locals, a, b) {return a(self, locals)&&b(self, locals);},
- '||':function(self, locals, a, b) {return a(self, locals)||b(self, locals);},
+ '*':function(self, locals, a, b) {return a(self, locals) * b(self, locals);},
+ '/':function(self, locals, a, b) {return a(self, locals) / b(self, locals);},
+ '%':function(self, locals, a, b) {return a(self, locals) % b(self, locals);},
+ '===':function(self, locals, a, b) {return a(self, locals) === b(self, locals);},
+ '!==':function(self, locals, a, b) {return a(self, locals) !== b(self, locals);},
+ '==':function(self, locals, a, b) {return a(self, locals) == b(self, locals);},
+ '!=':function(self, locals, a, b) {return a(self, locals) != b(self, locals);},
+ '<':function(self, locals, a, b) {return a(self, locals) < b(self, locals);},
+ '>':function(self, locals, a, b) {return a(self, locals) > b(self, locals);},
+ '<=':function(self, locals, a, b) {return a(self, locals) <= b(self, locals);},
+ '>=':function(self, locals, a, b) {return a(self, locals) >= b(self, locals);},
+ '&&':function(self, locals, a, b) {return a(self, locals) && b(self, locals);},
+ '||':function(self, locals, a, b) {return a(self, locals) || b(self, locals);},
'!':function(self, locals, a) {return !a(self, locals);},
//Tokenized as operators but parsed as assignment/filters
'=':true,
'|':true
@@ -20733,67 +20765,54 @@
constructor: Lexer,
lex: function(text) {
this.text = text;
this.index = 0;
- this.ch = undefined;
this.tokens = [];
while (this.index < this.text.length) {
- this.ch = this.text.charAt(this.index);
- if (this.is('"\'')) {
- this.readString(this.ch);
- } else if (this.isNumber(this.ch) || this.is('.') && this.isNumber(this.peek())) {
+ var ch = this.text.charAt(this.index);
+ if (ch === '"' || ch === "'") {
+ this.readString(ch);
+ } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {
this.readNumber();
- } else if (this.isIdent(this.ch)) {
+ } else if (this.isIdent(ch)) {
this.readIdent();
- } else if (this.is('(){}[].,;:?')) {
- this.tokens.push({
- index: this.index,
- text: this.ch
- });
+ } else if (this.is(ch, '(){}[].,;:?')) {
+ this.tokens.push({index: this.index, text: ch});
this.index++;
- } else if (this.isWhitespace(this.ch)) {
+ } else if (this.isWhitespace(ch)) {
this.index++;
} else {
- var ch2 = this.ch + this.peek();
+ var ch2 = ch + this.peek();
var ch3 = ch2 + this.peek(2);
- var fn = OPERATORS[this.ch];
- var fn2 = OPERATORS[ch2];
- var fn3 = OPERATORS[ch3];
- if (fn3) {
- this.tokens.push({index: this.index, text: ch3, fn: fn3});
- this.index += 3;
- } else if (fn2) {
- this.tokens.push({index: this.index, text: ch2, fn: fn2});
- this.index += 2;
- } else if (fn) {
- this.tokens.push({
- index: this.index,
- text: this.ch,
- fn: fn
- });
- this.index += 1;
+ var op1 = OPERATORS[ch];
+ var op2 = OPERATORS[ch2];
+ var op3 = OPERATORS[ch3];
+ if (op1 || op2 || op3) {
+ var token = op3 ? ch3 : (op2 ? ch2 : ch);
+ this.tokens.push({index: this.index, text: token, operator: true});
+ this.index += token.length;
} else {
this.throwError('Unexpected next character ', this.index, this.index + 1);
}
}
}
return this.tokens;
},
- is: function(chars) {
- return chars.indexOf(this.ch) !== -1;
+ is: function(ch, chars) {
+ return chars.indexOf(ch) !== -1;
},
peek: function(i) {
var num = i || 1;
return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;
},
isNumber: function(ch) {
- return ('0' <= ch && ch <= '9');
+ return ('0' <= ch && ch <= '9') && typeof ch === "string";
},
isWhitespace: function(ch) {
// IE treats non-breaking space as \u00A0
return (ch === ' ' || ch === '\r' || ch === '\t' ||
@@ -20842,83 +20861,32 @@
break;
}
}
this.index++;
}
- number = 1 * number;
this.tokens.push({
index: start,
text: number,
constant: true,
- fn: function() { return number; }
+ value: Number(number)
});
},
readIdent: function() {
- var expression = this.text;
-
- var ident = '';
var start = this.index;
-
- var lastDot, peekIndex, methodName, ch;
-
while (this.index < this.text.length) {
- ch = this.text.charAt(this.index);
- if (ch === '.' || this.isIdent(ch) || this.isNumber(ch)) {
- if (ch === '.') lastDot = this.index;
- ident += ch;
- } else {
+ var ch = this.text.charAt(this.index);
+ if (!(this.isIdent(ch) || this.isNumber(ch))) {
break;
}
this.index++;
}
-
- //check if the identifier ends with . and if so move back one char
- if (lastDot && ident[ident.length - 1] === '.') {
- this.index--;
- ident = ident.slice(0, -1);
- lastDot = ident.lastIndexOf('.');
- if (lastDot === -1) {
- lastDot = undefined;
- }
- }
-
- //check if this is not a method invocation and if it is back out to last dot
- if (lastDot) {
- peekIndex = this.index;
- while (peekIndex < this.text.length) {
- ch = this.text.charAt(peekIndex);
- if (ch === '(') {
- methodName = ident.substr(lastDot - start + 1);
- ident = ident.substr(0, lastDot - start);
- this.index = peekIndex;
- break;
- }
- if (this.isWhitespace(ch)) {
- peekIndex++;
- } else {
- break;
- }
- }
- }
-
this.tokens.push({
index: start,
- text: ident,
- fn: CONSTANTS[ident] || getterFn(ident, this.options, expression)
+ text: this.text.slice(start, this.index),
+ identifier: true
});
-
- if (methodName) {
- this.tokens.push({
- index: lastDot,
- text: '.'
- });
- this.tokens.push({
- index: lastDot + 1,
- text: methodName
- });
- }
},
readString: function(quote) {
var start = this.index;
this.index++;
@@ -20945,13 +20913,12 @@
} else if (ch === quote) {
this.index++;
this.tokens.push({
index: start,
text: rawString,
- string: string,
constant: true,
- fn: function() { return string; }
+ value: string
});
return;
} else {
string += ch;
}
@@ -21008,20 +20975,16 @@
this.consume(')');
} else if (this.expect('[')) {
primary = this.arrayDeclaration();
} else if (this.expect('{')) {
primary = this.object();
+ } else if (this.peek().identifier) {
+ primary = this.identifier();
+ } else if (this.peek().constant) {
+ primary = this.constant();
} else {
- var token = this.expect();
- primary = token.fn;
- if (!primary) {
- this.throwError('not a primary expression', token);
- }
- if (token.constant) {
- primary.constant = true;
- primary.literal = true;
- }
+ this.throwError('not a primary expression', this.peek());
}
var next, context;
while ((next = this.expect('(', '[', '.'))) {
if (next.text === '(') {
@@ -21051,12 +21014,15 @@
throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
return this.tokens[0];
},
peek: function(e1, e2, e3, e4) {
- if (this.tokens.length > 0) {
- var token = this.tokens[0];
+ return this.peekAhead(0, e1, e2, e3, e4);
+ },
+ peekAhead: function(i, e1, e2, e3, e4) {
+ if (this.tokens.length > i) {
+ var token = this.tokens[i];
var t = token.text;
if (t === e1 || t === e2 || t === e3 || t === e4 ||
(!e1 && !e2 && !e3 && !e4)) {
return token;
}
@@ -21072,33 +21038,63 @@
}
return false;
},
consume: function(e1) {
- if (!this.expect(e1)) {
+ if (this.tokens.length === 0) {
+ throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
+ }
+
+ var token = this.expect(e1);
+ if (!token) {
this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());
}
+ return token;
},
- unaryFn: function(fn, right) {
+ unaryFn: function(op, right) {
+ var fn = OPERATORS[op];
return extend(function $parseUnaryFn(self, locals) {
return fn(self, locals, right);
}, {
constant:right.constant,
inputs: [right]
});
},
- binaryFn: function(left, fn, right, isBranching) {
+ binaryFn: function(left, op, right, isBranching) {
+ var fn = OPERATORS[op];
return extend(function $parseBinaryFn(self, locals) {
return fn(self, locals, left, right);
}, {
constant: left.constant && right.constant,
inputs: !isBranching && [left, right]
});
},
+ identifier: function() {
+ var id = this.consume().text;
+
+ //Continue reading each `.identifier` unless it is a method invocation
+ while (this.peek('.') && this.peekAhead(1).identifier && !this.peekAhead(2, '(')) {
+ id += this.consume().text + this.consume().text;
+ }
+
+ return CONSTANTS[id] || getterFn(id, this.options, this.text);
+ },
+
+ constant: function() {
+ var value = this.consume().value;
+
+ return extend(function $parseConstant() {
+ return value;
+ }, {
+ constant: true,
+ literal: true
+ });
+ },
+
statements: function() {
var statements = [];
while (true) {
if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))
statements.push(this.filterChain());
@@ -21126,12 +21122,11 @@
}
return left;
},
filter: function(inputFn) {
- var token = this.expect();
- var fn = this.$filter(token.text);
+ var fn = this.$filter(this.consume().text);
var argsFn;
var args;
if (this.peek(':')) {
argsFn = [];
@@ -21190,97 +21185,94 @@
var left = this.logicalOR();
var middle;
var token;
if ((token = this.expect('?'))) {
middle = this.assignment();
- if ((token = this.expect(':'))) {
+ if (this.consume(':')) {
var right = this.assignment();
return extend(function $parseTernary(self, locals) {
return left(self, locals) ? middle(self, locals) : right(self, locals);
}, {
constant: left.constant && middle.constant && right.constant
});
-
- } else {
- this.throwError('expected :', token);
}
}
return left;
},
logicalOR: function() {
var left = this.logicalAND();
var token;
while ((token = this.expect('||'))) {
- left = this.binaryFn(left, token.fn, this.logicalAND(), true);
+ left = this.binaryFn(left, token.text, this.logicalAND(), true);
}
return left;
},
logicalAND: function() {
var left = this.equality();
var token;
if ((token = this.expect('&&'))) {
- left = this.binaryFn(left, token.fn, this.logicalAND(), true);
+ left = this.binaryFn(left, token.text, this.logicalAND(), true);
}
return left;
},
equality: function() {
var left = this.relational();
var token;
if ((token = this.expect('==','!=','===','!=='))) {
- left = this.binaryFn(left, token.fn, this.equality());
+ left = this.binaryFn(left, token.text, this.equality());
}
return left;
},
relational: function() {
var left = this.additive();
var token;
if ((token = this.expect('<', '>', '<=', '>='))) {
- left = this.binaryFn(left, token.fn, this.relational());
+ left = this.binaryFn(left, token.text, this.relational());
}
return left;
},
additive: function() {
var left = this.multiplicative();
var token;
while ((token = this.expect('+','-'))) {
- left = this.binaryFn(left, token.fn, this.multiplicative());
+ left = this.binaryFn(left, token.text, this.multiplicative());
}
return left;
},
multiplicative: function() {
var left = this.unary();
var token;
while ((token = this.expect('*','/','%'))) {
- left = this.binaryFn(left, token.fn, this.unary());
+ left = this.binaryFn(left, token.text, this.unary());
}
return left;
},
unary: function() {
var token;
if (this.expect('+')) {
return this.primary();
} else if ((token = this.expect('-'))) {
- return this.binaryFn(Parser.ZERO, token.fn, this.unary());
+ return this.binaryFn(Parser.ZERO, token.text, this.unary());
} else if ((token = this.expect('!'))) {
- return this.unaryFn(token.fn, this.unary());
+ return this.unaryFn(token.text, this.unary());
} else {
return this.primary();
}
},
fieldAccess: function(object) {
var expression = this.text;
- var field = this.expect().text;
+ var field = this.consume().text;
var getter = getterFn(field, this.options, expression);
return extend(function $parseFieldAccess(scope, locals, self) {
return getter(self || object(scope, locals));
}, {
@@ -21361,12 +21353,11 @@
do {
if (this.peek(']')) {
// Support trailing commas per ES5.1.
break;
}
- var elementFn = this.expression();
- elementFns.push(elementFn);
+ elementFns.push(this.expression());
} while (this.expect(','));
}
this.consume(']');
return extend(function $parseArrayLiteral(self, locals) {
@@ -21388,15 +21379,20 @@
do {
if (this.peek('}')) {
// Support trailing commas per ES5.1.
break;
}
- var token = this.expect();
- keys.push(token.string || token.text);
+ var token = this.consume();
+ if (token.constant) {
+ keys.push(token.value);
+ } else if (token.identifier) {
+ keys.push(token.text);
+ } else {
+ this.throwError("invalid key", token);
+ }
this.consume(':');
- var value = this.expression();
- valueFns.push(value);
+ valueFns.push(this.expression());
} while (this.expect(','));
}
this.consume('}');
return extend(function $parseObjectLiteral(self, locals) {
@@ -21834,17 +21830,25 @@
}, objectEquality);
}
function addInterceptor(parsedExpression, interceptorFn) {
if (!interceptorFn) return parsedExpression;
+ var watchDelegate = parsedExpression.$$watchDelegate;
- var fn = function interceptedExpression(scope, locals) {
+ var regularWatch =
+ watchDelegate !== oneTimeLiteralWatchDelegate &&
+ watchDelegate !== oneTimeWatchDelegate;
+
+ var fn = regularWatch ? function regularInterceptedExpression(scope, locals) {
var value = parsedExpression(scope, locals);
+ return interceptorFn(value, scope, locals);
+ } : function oneTimeInterceptedExpression(scope, locals) {
+ var value = parsedExpression(scope, locals);
var result = interceptorFn(value, scope, locals);
// we only return the interceptor's result if the
// initial value is defined (for bind-once)
- return isDefined(value) || interceptorFn.$stateful ? result : value;
+ return isDefined(value) ? result : value;
};
// Propagate $$watchDelegates other then inputsWatchDelegate
if (parsedExpression.$$watchDelegate &&
parsedExpression.$$watchDelegate !== inputsWatchDelegate) {
@@ -21865,12 +21869,16 @@
* @ngdoc service
* @name $q
* @requires $rootScope
*
* @description
- * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).
+ * A service that helps you run functions asynchronously, and use their return values (or exceptions)
+ * when they are done processing.
*
+ * This is an implementation of promises/deferred objects inspired by
+ * [Kris Kowal's Q](https://github.com/kriskowal/q).
+ *
* $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred
* implementations, and the other which resembles ES6 promises to some degree.
*
* # $q constructor
*
@@ -22001,20 +22009,16 @@
* `notifyCallback` method. The promise cannot be resolved or rejected from the notifyCallback
* method.
*
* - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`
*
- * - `finally(callback)` – allows you to observe either the fulfillment or rejection of a promise,
+ * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise,
* but to do so without modifying the final value. This is useful to release resources or do some
* clean-up that needs to be done whether the promise was rejected or resolved. See the [full
* specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for
* more information.
*
- * Because `finally` is a reserved word in JavaScript and reserved keywords are not supported as
- * property names by ES3, you'll need to invoke the method like `promise['finally'](callback)` to
- * make your code IE8 and Android 2.x compatible.
- *
* # Chaining promises
*
* Because calling the `then` method of a promise returns a new derived promise, it is easily
* possible to create a chain of promises:
*
@@ -23233,15 +23237,15 @@
watch.last = watch.eq ? copy(value, null) : value;
watch.fn(value, ((last === initWatchVal) ? value : last), current);
if (ttl < 5) {
logIdx = 4 - ttl;
if (!watchLog[logIdx]) watchLog[logIdx] = [];
- logMsg = (isFunction(watch.exp))
- ? 'fn: ' + (watch.exp.name || watch.exp.toString())
- : watch.exp;
- logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);
- watchLog[logIdx].push(logMsg);
+ watchLog[logIdx].push({
+ msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,
+ newVal: value,
+ oldVal: last
+ });
}
} else if (watch === lastDirtyWatch) {
// If the most recently dirty watcher is now clean, short circuit since the remaining watchers
// have already been tested.
dirty = false;
@@ -23270,11 +23274,11 @@
if ((dirty || asyncQueue.length) && !(ttl--)) {
clearPhase();
throw $rootScopeMinErr('infdig',
'{0} $digest() iterations reached. Aborting!\n' +
'Watchers fired in the last 5 iterations: {1}',
- TTL, toJson(watchLog));
+ TTL, watchLog);
}
} while (dirty || asyncQueue.length);
clearPhase();
@@ -23621,11 +23625,11 @@
i, length;
do {
namedListeners = scope.$$listeners[name] || empty;
event.currentScope = scope;
- for (i=0, length=namedListeners.length; i<length; i++) {
+ for (i = 0, length = namedListeners.length; i < length; i++) {
// if listeners were deregistered, defragment the array
if (!namedListeners[i]) {
namedListeners.splice(i, 1);
i--;
@@ -23695,11 +23699,11 @@
//down while you can, then up and next sibling or up and next sibling until back at root
while ((current = next)) {
event.currentScope = current;
listeners = current.$$listeners[name] || [];
- for (i=0, length = listeners.length; i<length; i++) {
+ for (i = 0, length = listeners.length; i < length; i++) {
// if listeners were deregistered, defragment the array
if (!listeners[i]) {
listeners.splice(i, 1);
i--;
length--;
@@ -23851,11 +23855,11 @@
return function sanitizeUri(uri, isImage) {
var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;
var normalizedVal;
normalizedVal = urlResolve(uri).href;
if (normalizedVal !== '' && !normalizedVal.match(regex)) {
- return 'unsafe:'+normalizedVal;
+ return 'unsafe:' + normalizedVal;
}
return uri;
};
};
}
@@ -24950,11 +24954,11 @@
}
transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));
animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));
- if (android && (!transitions||!animations)) {
+ if (android && (!transitions || !animations)) {
transitions = isString(document.body.style.webkitTransition);
animations = isString(document.body.style.webkitAnimation);
}
}
@@ -25021,11 +25025,11 @@
var transformResponse = $http.defaults && $http.defaults.transformResponse;
if (isArray(transformResponse)) {
var original = transformResponse;
transformResponse = [];
- for (var i=0; i<original.length; ++i) {
+ for (var i = 0; i < original.length; ++i) {
var transformer = original[i];
if (transformer !== defaultHttpResponseTransform) {
transformResponse.push(transformer);
}
}
@@ -25265,11 +25269,11 @@
// cause us to break tests. In addition, when the browser resolves a URL for XHR, it
// doesn't know about mocked locations and resolves URLs to the real document - which is
// exactly the behavior needed here. There is little value is mocking these out for this
// service.
var urlParsingNode = document.createElement("a");
-var originUrl = urlResolve(window.location.href, true);
+var originUrl = urlResolve(window.location.href);
/**
*
* Implementation Notes for non-IE browsers
@@ -25320,11 +25324,11 @@
* | hostname | The hostname
* | port | The port, without ":"
* | pathname | The pathname, beginning with "/"
*
*/
-function urlResolve(url, base) {
+function urlResolve(url) {
var href = url;
if (msie) {
// Normalize before parse. Refer Implementation Notes on why this is
// done in two steps on IE.
@@ -25700,12 +25704,12 @@
return true;
}
}
return false;
}
- text = (''+text).toLowerCase();
- return (''+obj).toLowerCase().indexOf(text) > -1;
+ text = ('' + text).toLowerCase();
+ return ('' + obj).toLowerCase().indexOf(text) > -1;
};
}
}
var search = function(obj, text) {
@@ -25961,19 +25965,19 @@
group = pattern.gSize;
if (whole.length >= (lgroup + group)) {
pos = whole.length - lgroup;
for (i = 0; i < pos; i++) {
- if ((pos - i)%group === 0 && i !== 0) {
+ if ((pos - i) % group === 0 && i !== 0) {
formatedText += groupSep;
}
formatedText += whole.charAt(i);
}
}
for (i = pos; i < whole.length; i++) {
- if ((whole.length - i)%lgroup === 0 && i !== 0) {
+ if ((whole.length - i) % lgroup === 0 && i !== 0) {
formatedText += groupSep;
}
formatedText += whole.charAt(i);
}
@@ -26209,14 +26213,14 @@
if (match[9]) {
tzHour = int(match[9] + match[10]);
tzMin = int(match[9] + match[11]);
}
dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));
- var h = int(match[4]||0) - tzHour;
- var m = int(match[5]||0) - tzMin;
- var s = int(match[6]||0);
- var ms = Math.round(parseFloat('0.' + (match[7]||0)) * 1000);
+ var h = int(match[4] || 0) - tzHour;
+ var m = int(match[5] || 0) - tzMin;
+ var s = int(match[6] || 0);
+ var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);
timeSetter.call(date, h, m, s, ms);
return date;
}
return string;
}
@@ -26444,11 +26448,11 @@
} else {
i = input.length + limit;
n = input.length;
}
- for (; i<n; i++) {
+ for (; i < n; i++) {
out.push(input[i]);
}
return out;
};
@@ -26571,11 +26575,11 @@
*/
orderByFilter.$inject = ['$parse'];
function orderByFilter($parse) {
return function(array, sortPredicate, reverseOrder) {
if (!(isArrayLike(array))) return array;
- sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
+ sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate];
if (sortPredicate.length === 0) { sortPredicate = ['+']; }
sortPredicate = sortPredicate.map(function(predicate) {
var descending = false, get = predicate || identity;
if (isString(predicate)) {
if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
@@ -26598,13 +26602,11 @@
}
return reverseComparator(function(a, b) {
return compare(get(a),get(b));
}, descending);
});
- var arrayCopy = [];
- for (var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }
- return arrayCopy.sort(reverseComparator(comparator, reverseOrder));
+ return slice.call(array).sort(reverseComparator(comparator, reverseOrder));
function comparator(o1, o2) {
for (var i = 0; i < sortPredicate.length; i++) {
var comp = sortPredicate[i](o1, o2);
if (comp !== 0) return comp;
@@ -27662,13 +27664,18 @@
* `required` when you want to data-bind to the `required` attribute.
* @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
* minlength.
* @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
* maxlength.
- * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object then this is used directly.
+ * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
+ * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
* @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.
@@ -28205,13 +28212,18 @@
* `required` when you want to data-bind to the `required` attribute.
* @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
* minlength.
* @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
* maxlength.
- * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object then this is used directly.
+ * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
+ * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
*
* @example
<example name="number-input-directive" module="numberExample">
@@ -28287,13 +28299,18 @@
* `required` when you want to data-bind to the `required` attribute.
* @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
* minlength.
* @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
* maxlength.
- * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object then this is used directly.
+ * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
+ * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
*
* @example
<example name="url-input-directive" module="urlExample">
@@ -28370,13 +28387,18 @@
* `required` when you want to data-bind to the `required` attribute.
* @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
* minlength.
* @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
* maxlength.
- * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object then this is used directly.
+ * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
+ * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
*
* @example
<example name="email-input-directive" module="emailExample">
@@ -28683,12 +28705,12 @@
if (isString(iso)) {
// When a date is JSON'ified to wraps itself inside of an extra
// set of double quotes. This makes the date parsing code unable
// to match the date string and parse it as a date.
- if (iso.charAt(0) == '"' && iso.charAt(iso.length-1) == '"') {
- iso = iso.substring(1, iso.length-1);
+ if (iso.charAt(0) == '"' && iso.charAt(iso.length - 1) == '"') {
+ iso = iso.substring(1, iso.length - 1);
}
if (ISO_DATE_REGEXP.test(iso)) {
return new Date(iso);
}
regexp.lastIndex = 0;
@@ -29131,17 +29153,22 @@
* @name ngModel.NgModelController
*
* @property {string} $viewValue Actual string value in the view.
* @property {*} $modelValue The value in the model that the control is bound to.
* @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
- the control reads value from the DOM. The functions are called in array order, each passing the value
- through to the next. The last return value is forwarded to the $validators collection.
- Used to sanitize / convert the value.
- Returning undefined from a parser means a parse error occurred. No $validators will
- run and the 'ngModel' will not be updated until the parse error is resolved. The parse error is stored
- in 'ngModel.$error.parse'.
+ the control reads value from the DOM. The functions are called in array order, each passing
+ its return value through to the next. The last return value is forwarded to the
+ {@link ngModel.NgModelController#$validators `$validators`} collection.
+Parsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue
+`$viewValue`}.
+
+Returning `undefined` from a parser means a parse error occurred. In that case,
+no {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel`
+will be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`}
+is set to `true`. The parse error is stored in `ngModel.$error.parse`.
+
*
* @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever
the model value changes. The functions are called in reverse array order, each passing the value through to the
next. The last return value is used as the actual DOM value.
Used to format / convert values for display in the control.
@@ -29261,11 +29288,11 @@
element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
};
// Listen for change events to enable binding
element.on('blur keyup change', function() {
- scope.$apply(read);
+ scope.$evalAsync(read);
});
read(); // initialize
// Write data to the model
function read() {
@@ -30197,11 +30224,11 @@
if (!ctrl) return;
var regexp, patternExp = attr.ngPattern || attr.pattern;
attr.$observe('pattern', function(regex) {
if (isString(regex) && regex.length > 0) {
- regex = new RegExp(regex);
+ regex = new RegExp('^' + regex + '$');
}
if (regex && !regex.test) {
throw minErr('ngPattern')('noregexp',
'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp,
@@ -30488,11 +30515,11 @@
* to have access to the updated model.
*
* `ngModelOptions` has an effect on the element it's declared on and its descendants.
*
* @param {Object} ngModelOptions options to apply to the current model. Valid keys are:
- * - `updateOn`: string specifying which event should be the input bound to. You can set several
+ * - `updateOn`: string specifying which event should the input be bound to. You can set several
* events using an space delimited list. There is a special event called `default` that
* matches the default events belonging of the control.
* - `debounce`: integer value which contains the debounce model update value in milliseconds. A
* value of 0 triggers an immediate update. If an object is supplied instead, you can specify a
* custom value for each event. For example:
@@ -33356,11 +33383,11 @@
forEach(nextBlockOrder, function(block) {
if (block && block.scope) lastBlockMap[block.id] = block;
});
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));
+ expression, trackById, value);
} else {
// new never before seen block
nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined};
nextBlockMap[trackById] = true;
}
@@ -34162,11 +34189,11 @@
* `ngOptions` comprehension_expression.
*
* In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a
* similar result. However, the `ngOptions` provides some benefits such as reducing memory and
* increasing speed by not creating a new scope for each repeated instance, as well as providing
- * more flexibility in how the `select`'s model is assigned via `select as`. `ngOptions should be
+ * more flexibility in how the `select`'s model is assigned via `select as`. `ngOptions` should be
* used when the `select` model needs to be bound to a non-string value. This is because an option
* element can only be bound to string values at present.
*
* When an item in the `<select>` menu is selected, the array element or object property
* represented by the selected option will be bound to the model identified by the `ngModel`
@@ -34760,17 +34787,18 @@
}
lastElement = null; // start at the beginning
for (index = 0, length = optionGroup.length; index < length; index++) {
option = optionGroup[index];
- if ((existingOption = existingOptions[index+1])) {
+ if ((existingOption = existingOptions[index + 1])) {
// reuse elements
lastElement = existingOption.element;
if (existingOption.label !== option.label) {
updateLabelMap(labelMap, existingOption.label, false);
updateLabelMap(labelMap, option.label, true);
lastElement.text(existingOption.label = option.label);
+ lastElement.prop('label', existingOption.label);
}
if (existingOption.id !== option.id) {
lastElement.val(existingOption.id = option.id);
}
// lastElement.prop('selected') provided by jQuery has side-effects
@@ -34796,10 +34824,11 @@
// rather then the element.
(element = optionTemplate.clone())
.val(option.id)
.prop('selected', option.selected)
.attr('selected', option.selected)
+ .prop('label', option.label)
.text(option.label);
}
existingOptions.push(existingOption = {
element: element,
@@ -35107,14 +35136,14 @@
// Clean up the stack trace line
if (line) {
if (line.indexOf('@') !== -1) {
// Firefox
- line = line.substring(line.indexOf('@')+1);
+ line = line.substring(line.indexOf('@') + 1);
} else {
// Chrome
- line = line.substring(line.indexOf('(')+1).replace(')', '');
+ line = line.substring(line.indexOf('(') + 1).replace(')', '');
}
}
return line || '';
};
@@ -35194,11 +35223,11 @@
selection.each(function() {
var element = windowJquery(this),
bindings;
if (bindings = element.data('$binding')) {
- for (var expressions = [], binding, j=0, jj=bindings.length; j<jj; j++) {
+ for (var expressions = [], binding, j=0, jj=bindings.length; j < jj; j++) {
binding = bindings[j];
if (binding.expressions) {
expressions = binding.expressions;
} else {
@@ -35570,11 +35599,11 @@
* @param {string} name Name of the test.
* @param {function()} body Body of the block.
*/
angular.scenario.Describe.prototype.iit = function(name, body) {
this.it.apply(this, arguments);
- this.its[this.its.length-1].only = true;
+ this.its[this.its.length - 1].only = true;
};
/**
* Use to disable a test block.
*/
@@ -35882,11 +35911,11 @@
* Gets the most recent step.
*
* @return {Object} the step
*/
angular.scenario.ObjectModel.Spec.prototype.getLastStep = function() {
- return this.steps[this.steps.length-1];
+ return this.steps[this.steps.length - 1];
};
/**
* Set status of the Spec from given Step
*
@@ -36457,10 +36486,10 @@
* ex.
* using('#foo', "'Foo' text field").input('bar')
*/
angular.scenario.dsl('using', function() {
return function(selector, label) {
- this.selector = _jQuery.trim((this.selector||'') + ' ' + selector);
+ this.selector = _jQuery.trim((this.selector || '') + ' ' + selector);
if (angular.isString(label) && label.length) {
this.label = label + ' ( ' + this.selector + ' )';
} else {
this.label = this.selector;
}
\ No newline at end of file