angular-gem 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. checksums.yaml +8 -8
  2. data/lib/angular-gem/version.rb +1 -1
  3. data/vendor/assets/javascripts/1.3.1/angular-animate.js +2136 -0
  4. data/vendor/assets/javascripts/1.3.1/angular-aria.js +250 -0
  5. data/vendor/assets/javascripts/1.3.1/angular-cookies.js +206 -0
  6. data/vendor/assets/javascripts/1.3.1/angular-loader.js +422 -0
  7. data/vendor/assets/javascripts/1.3.1/angular-messages.js +400 -0
  8. data/vendor/assets/javascripts/1.3.1/angular-mocks.js +2289 -0
  9. data/vendor/assets/javascripts/1.3.1/angular-resource.js +667 -0
  10. data/vendor/assets/javascripts/1.3.1/angular-route.js +978 -0
  11. data/vendor/assets/javascripts/1.3.1/angular-sanitize.js +678 -0
  12. data/vendor/assets/javascripts/1.3.1/angular-scenario.js +36979 -0
  13. data/vendor/assets/javascripts/1.3.1/angular-touch.js +622 -0
  14. data/vendor/assets/javascripts/1.3.1/angular.js +25625 -0
  15. data/vendor/assets/javascripts/angular-animate.js +78 -54
  16. data/vendor/assets/javascripts/angular-aria.js +5 -5
  17. data/vendor/assets/javascripts/angular-cookies.js +4 -4
  18. data/vendor/assets/javascripts/angular-loader.js +6 -6
  19. data/vendor/assets/javascripts/angular-messages.js +15 -15
  20. data/vendor/assets/javascripts/angular-mocks.js +34 -32
  21. data/vendor/assets/javascripts/angular-resource.js +22 -22
  22. data/vendor/assets/javascripts/angular-route.js +8 -8
  23. data/vendor/assets/javascripts/angular-sanitize.js +94 -63
  24. data/vendor/assets/javascripts/angular-scenario.js +532 -497
  25. data/vendor/assets/javascripts/angular-touch.js +3 -3
  26. data/vendor/assets/javascripts/angular.js +516 -475
  27. metadata +14 -2
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.0
2
+ * @license AngularJS v1.3.1
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -39,7 +39,7 @@ var ngRouteModule = angular.module('ngRoute', ['ng']).
39
39
  * ## Dependencies
40
40
  * Requires the {@link ngRoute `ngRoute`} module to be installed.
41
41
  */
42
- function $RouteProvider(){
42
+ function $RouteProvider() {
43
43
  function inherit(parent, extra) {
44
44
  return angular.extend(new (angular.extend(function() {}, {prototype:parent}))(), extra);
45
45
  }
@@ -188,7 +188,7 @@ function $RouteProvider(){
188
188
 
189
189
  path = path
190
190
  .replace(/([().])/g, '\\$1')
191
- .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option){
191
+ .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option) {
192
192
  var optional = option === '?' ? option : null;
193
193
  var star = option === '*' ? option : null;
194
194
  keys.push({ name: key, optional: !!optional });
@@ -870,7 +870,7 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory);
870
870
  * Emitted every time the ngView content is reloaded.
871
871
  */
872
872
  ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
873
- function ngViewFactory( $route, $anchorScroll, $animate) {
873
+ function ngViewFactory($route, $anchorScroll, $animate) {
874
874
  return {
875
875
  restrict: 'ECA',
876
876
  terminal: true,
@@ -887,16 +887,16 @@ function ngViewFactory( $route, $anchorScroll, $animate) {
887
887
  update();
888
888
 
889
889
  function cleanupLastView() {
890
- if(previousLeaveAnimation) {
890
+ if (previousLeaveAnimation) {
891
891
  $animate.cancel(previousLeaveAnimation);
892
892
  previousLeaveAnimation = null;
893
893
  }
894
894
 
895
- if(currentScope) {
895
+ if (currentScope) {
896
896
  currentScope.$destroy();
897
897
  currentScope = null;
898
898
  }
899
- if(currentElement) {
899
+ if (currentElement) {
900
900
  previousLeaveAnimation = $animate.leave(currentElement);
901
901
  previousLeaveAnimation.then(function() {
902
902
  previousLeaveAnimation = null;
@@ -920,7 +920,7 @@ function ngViewFactory( $route, $anchorScroll, $animate) {
920
920
  // function is called before linking the content, which would apply child
921
921
  // directives to non existing elements.
922
922
  var clone = $transclude(newScope, function(clone) {
923
- $animate.enter(clone, null, currentElement || $element).then(function onNgViewEnter () {
923
+ $animate.enter(clone, null, currentElement || $element).then(function onNgViewEnter() {
924
924
  if (angular.isDefined(autoScrollExp)
925
925
  && (!autoScrollExp || scope.$eval(autoScrollExp))) {
926
926
  $anchorScroll();
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.0
2
+ * @license AngularJS v1.3.1
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -45,16 +45,16 @@ var $sanitizeMinErr = angular.$$minErr('$sanitize');
45
45
  * @kind function
46
46
  *
47
47
  * @description
48
- * The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are
48
+ * The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are
49
49
  * then serialized back to properly escaped html string. This means that no unsafe input can make
50
50
  * it into the returned string, however, since our parser is more strict than a typical browser
51
51
  * parser, it's possible that some obscure input, which would be recognized as valid HTML by a
52
- * browser, won't make it through the sanitizer.
52
+ * browser, won't make it through the sanitizer. The input may also contain SVG markup.
53
53
  * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and
54
54
  * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.
55
55
  *
56
- * @param {string} html Html input.
57
- * @returns {string} Sanitized html.
56
+ * @param {string} html HTML input.
57
+ * @returns {string} Sanitized HTML.
58
58
  *
59
59
  * @example
60
60
  <example module="sanitizeExample" deps="angular-sanitize.js">
@@ -198,6 +198,12 @@ var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a
198
198
  "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
199
199
  "samp,small,span,strike,strong,sub,sup,time,tt,u,var"));
200
200
 
201
+ // SVG Elements
202
+ // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements
203
+ var svgElements = makeMap("animate,animateColor,animateMotion,animateTransform,circle,defs," +
204
+ "desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient," +
205
+ "line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set," +
206
+ "stop,svg,switch,text,title,tspan,use");
201
207
 
202
208
  // Special Elements (can contain anything)
203
209
  var specialElements = makeMap("script,style");
@@ -206,16 +212,41 @@ var validElements = angular.extend({},
206
212
  voidElements,
207
213
  blockElements,
208
214
  inlineElements,
209
- optionalEndTagElements);
215
+ optionalEndTagElements,
216
+ svgElements);
210
217
 
211
218
  //Attributes that have href and hence need to be sanitized
212
- var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap");
213
- var validAttrs = angular.extend({}, uriAttrs, makeMap(
214
- 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+
219
+ var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap,xlink:href");
220
+
221
+ var htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+
215
222
  'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+
216
223
  'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+
217
224
  'scope,scrolling,shape,size,span,start,summary,target,title,type,'+
218
- 'valign,value,vspace,width'));
225
+ 'valign,value,vspace,width');
226
+
227
+ // SVG attributes (without "id" and "name" attributes)
228
+ // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
229
+ var svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,'+
230
+ 'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,'+
231
+ 'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,'+
232
+ 'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,'+
233
+ 'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,'+
234
+ 'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,'+
235
+ 'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,'+
236
+ 'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,'+
237
+ 'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,'+
238
+ 'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,'+
239
+ 'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,'+
240
+ 'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,'+
241
+ 'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,'+
242
+ 'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,'+
243
+ 'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,'+
244
+ 'zoomAndPan');
245
+
246
+ var validAttrs = angular.extend({},
247
+ uriAttrs,
248
+ svgAttrs,
249
+ htmlAttrs);
219
250
 
220
251
  function makeMap(str) {
221
252
  var obj = {}, items = str.split(','), i;
@@ -236,7 +267,7 @@ function makeMap(str) {
236
267
  * @param {string} html string
237
268
  * @param {object} handler
238
269
  */
239
- function htmlParser( html, handler ) {
270
+ function htmlParser(html, handler) {
240
271
  if (typeof html !== 'string') {
241
272
  if (html === null || typeof html === 'undefined') {
242
273
  html = '';
@@ -247,50 +278,50 @@ function htmlParser( html, handler ) {
247
278
  var index, chars, match, stack = [], last = html, text;
248
279
  stack.last = function() { return stack[ stack.length - 1 ]; };
249
280
 
250
- while ( html ) {
281
+ while (html) {
251
282
  text = '';
252
283
  chars = true;
253
284
 
254
285
  // Make sure we're not in a script or style element
255
- if ( !stack.last() || !specialElements[ stack.last() ] ) {
286
+ if (!stack.last() || !specialElements[ stack.last() ]) {
256
287
 
257
288
  // Comment
258
- if ( html.indexOf("<!--") === 0 ) {
289
+ if (html.indexOf("<!--") === 0) {
259
290
  // comments containing -- are not allowed unless they terminate the comment
260
291
  index = html.indexOf("--", 4);
261
292
 
262
- if ( index >= 0 && html.lastIndexOf("-->", index) === index) {
263
- if (handler.comment) handler.comment( html.substring( 4, index ) );
264
- html = html.substring( index + 3 );
293
+ if (index >= 0 && html.lastIndexOf("-->", index) === index) {
294
+ if (handler.comment) handler.comment(html.substring(4, index));
295
+ html = html.substring(index + 3);
265
296
  chars = false;
266
297
  }
267
298
  // DOCTYPE
268
- } else if ( DOCTYPE_REGEXP.test(html) ) {
269
- match = html.match( DOCTYPE_REGEXP );
299
+ } else if (DOCTYPE_REGEXP.test(html)) {
300
+ match = html.match(DOCTYPE_REGEXP);
270
301
 
271
- if ( match ) {
272
- html = html.replace( match[0], '');
302
+ if (match) {
303
+ html = html.replace(match[0], '');
273
304
  chars = false;
274
305
  }
275
306
  // end tag
276
- } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {
277
- match = html.match( END_TAG_REGEXP );
307
+ } else if (BEGING_END_TAGE_REGEXP.test(html)) {
308
+ match = html.match(END_TAG_REGEXP);
278
309
 
279
- if ( match ) {
280
- html = html.substring( match[0].length );
281
- match[0].replace( END_TAG_REGEXP, parseEndTag );
310
+ if (match) {
311
+ html = html.substring(match[0].length);
312
+ match[0].replace(END_TAG_REGEXP, parseEndTag);
282
313
  chars = false;
283
314
  }
284
315
 
285
316
  // start tag
286
- } else if ( BEGIN_TAG_REGEXP.test(html) ) {
287
- match = html.match( START_TAG_REGEXP );
317
+ } else if (BEGIN_TAG_REGEXP.test(html)) {
318
+ match = html.match(START_TAG_REGEXP);
288
319
 
289
- if ( match ) {
320
+ if (match) {
290
321
  // We only have a valid start-tag if there is a '>'.
291
- if ( match[4] ) {
292
- html = html.substring( match[0].length );
293
- match[0].replace( START_TAG_REGEXP, parseStartTag );
322
+ if (match[4]) {
323
+ html = html.substring(match[0].length);
324
+ match[0].replace(START_TAG_REGEXP, parseStartTag);
294
325
  }
295
326
  chars = false;
296
327
  } else {
@@ -300,29 +331,29 @@ function htmlParser( html, handler ) {
300
331
  }
301
332
  }
302
333
 
303
- if ( chars ) {
334
+ if (chars) {
304
335
  index = html.indexOf("<");
305
336
 
306
- text += index < 0 ? html : html.substring( 0, index );
307
- html = index < 0 ? "" : html.substring( index );
337
+ text += index < 0 ? html : html.substring(0, index);
338
+ html = index < 0 ? "" : html.substring(index);
308
339
 
309
- if (handler.chars) handler.chars( decodeEntities(text) );
340
+ if (handler.chars) handler.chars(decodeEntities(text));
310
341
  }
311
342
 
312
343
  } else {
313
344
  html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'),
314
- function(all, text){
345
+ function(all, text) {
315
346
  text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1");
316
347
 
317
- if (handler.chars) handler.chars( decodeEntities(text) );
348
+ if (handler.chars) handler.chars(decodeEntities(text));
318
349
 
319
350
  return "";
320
351
  });
321
352
 
322
- parseEndTag( "", stack.last() );
353
+ parseEndTag("", stack.last());
323
354
  }
324
355
 
325
- if ( html == last ) {
356
+ if (html == last) {
326
357
  throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " +
327
358
  "of html: {0}", html);
328
359
  }
@@ -332,22 +363,22 @@ function htmlParser( html, handler ) {
332
363
  // Clean up any remaining tags
333
364
  parseEndTag();
334
365
 
335
- function parseStartTag( tag, tagName, rest, unary ) {
366
+ function parseStartTag(tag, tagName, rest, unary) {
336
367
  tagName = angular.lowercase(tagName);
337
- if ( blockElements[ tagName ] ) {
338
- while ( stack.last() && inlineElements[ stack.last() ] ) {
339
- parseEndTag( "", stack.last() );
368
+ if (blockElements[ tagName ]) {
369
+ while (stack.last() && inlineElements[ stack.last() ]) {
370
+ parseEndTag("", stack.last());
340
371
  }
341
372
  }
342
373
 
343
- if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {
344
- parseEndTag( "", tagName );
374
+ if (optionalEndTagElements[ tagName ] && stack.last() == tagName) {
375
+ parseEndTag("", tagName);
345
376
  }
346
377
 
347
378
  unary = voidElements[ tagName ] || !!unary;
348
379
 
349
- if ( !unary )
350
- stack.push( tagName );
380
+ if (!unary)
381
+ stack.push(tagName);
351
382
 
352
383
  var attrs = {};
353
384
 
@@ -360,22 +391,22 @@ function htmlParser( html, handler ) {
360
391
 
361
392
  attrs[name] = decodeEntities(value);
362
393
  });
363
- if (handler.start) handler.start( tagName, attrs, unary );
394
+ if (handler.start) handler.start(tagName, attrs, unary);
364
395
  }
365
396
 
366
- function parseEndTag( tag, tagName ) {
397
+ function parseEndTag(tag, tagName) {
367
398
  var pos = 0, i;
368
399
  tagName = angular.lowercase(tagName);
369
- if ( tagName )
400
+ if (tagName)
370
401
  // Find the closest opened tag of the same type
371
- for ( pos = stack.length - 1; pos >= 0; pos-- )
372
- if ( stack[ pos ] == tagName )
402
+ for (pos = stack.length - 1; pos >= 0; pos--)
403
+ if (stack[ pos ] == tagName)
373
404
  break;
374
405
 
375
- if ( pos >= 0 ) {
406
+ if (pos >= 0) {
376
407
  // Close all the open elements, up the stack
377
- for ( i = stack.length - 1; i >= pos; i-- )
378
- if (handler.end) handler.end( stack[ i ] );
408
+ for (i = stack.length - 1; i >= pos; i--)
409
+ if (handler.end) handler.end(stack[ i ]);
379
410
 
380
411
  // Remove the open elements from the stack
381
412
  stack.length = pos;
@@ -421,12 +452,12 @@ function decodeEntities(value) {
421
452
  function encodeEntities(value) {
422
453
  return value.
423
454
  replace(/&/g, '&amp;').
424
- replace(SURROGATE_PAIR_REGEXP, function (value) {
455
+ replace(SURROGATE_PAIR_REGEXP, function(value) {
425
456
  var hi = value.charCodeAt(0);
426
457
  var low = value.charCodeAt(1);
427
458
  return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
428
459
  }).
429
- replace(NON_ALPHANUMERIC_REGEXP, function(value){
460
+ replace(NON_ALPHANUMERIC_REGEXP, function(value) {
430
461
  return '&#' + value.charCodeAt(0) + ';';
431
462
  }).
432
463
  replace(/</g, '&lt;').
@@ -443,11 +474,11 @@ function encodeEntities(value) {
443
474
  * comment: function(text) {}
444
475
  * }
445
476
  */
446
- function htmlSanitizeWriter(buf, uriValidator){
477
+ function htmlSanitizeWriter(buf, uriValidator) {
447
478
  var ignore = false;
448
479
  var out = angular.bind(buf, buf.push);
449
480
  return {
450
- start: function(tag, attrs, unary){
481
+ start: function(tag, attrs, unary) {
451
482
  tag = angular.lowercase(tag);
452
483
  if (!ignore && specialElements[tag]) {
453
484
  ignore = tag;
@@ -455,7 +486,7 @@ function htmlSanitizeWriter(buf, uriValidator){
455
486
  if (!ignore && validElements[tag] === true) {
456
487
  out('<');
457
488
  out(tag);
458
- angular.forEach(attrs, function(value, key){
489
+ angular.forEach(attrs, function(value, key) {
459
490
  var lkey=angular.lowercase(key);
460
491
  var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');
461
492
  if (validAttrs[lkey] === true &&
@@ -470,7 +501,7 @@ function htmlSanitizeWriter(buf, uriValidator){
470
501
  out(unary ? '/>' : '>');
471
502
  }
472
503
  },
473
- end: function(tag){
504
+ end: function(tag) {
474
505
  tag = angular.lowercase(tag);
475
506
  if (!ignore && validElements[tag] === true) {
476
507
  out('</');
@@ -481,7 +512,7 @@ function htmlSanitizeWriter(buf, uriValidator){
481
512
  ignore = false;
482
513
  }
483
514
  },
484
- chars: function(chars){
515
+ chars: function(chars) {
485
516
  if (!ignore) {
486
517
  out(encodeEntities(chars));
487
518
  }
@@ -9190,7 +9190,7 @@ return jQuery;
9190
9190
  }));
9191
9191
 
9192
9192
  /**
9193
- * @license AngularJS v1.3.0
9193
+ * @license AngularJS v1.3.1
9194
9194
  * (c) 2010-2014 Google, Inc. http://angularjs.org
9195
9195
  * License: MIT
9196
9196
  */
@@ -9229,12 +9229,12 @@ return jQuery;
9229
9229
 
9230
9230
  function minErr(module, ErrorConstructor) {
9231
9231
  ErrorConstructor = ErrorConstructor || Error;
9232
- return function () {
9232
+ return function() {
9233
9233
  var code = arguments[0],
9234
9234
  prefix = '[' + (module ? module + ':' : '') + code + '] ',
9235
9235
  template = arguments[1],
9236
9236
  templateArgs = arguments,
9237
- stringify = function (obj) {
9237
+ stringify = function(obj) {
9238
9238
  if (typeof obj === 'function') {
9239
9239
  return obj.toString().replace(/ \{[\s\S]*$/, '');
9240
9240
  } else if (typeof obj === 'undefined') {
@@ -9246,7 +9246,7 @@ function minErr(module, ErrorConstructor) {
9246
9246
  },
9247
9247
  message, i;
9248
9248
 
9249
- message = prefix + template.replace(/\{\d+\}/g, function (match) {
9249
+ message = prefix + template.replace(/\{\d+\}/g, function(match) {
9250
9250
  var index = +match.slice(1, -1), arg;
9251
9251
 
9252
9252
  if (index + 2 < templateArgs.length) {
@@ -9263,7 +9263,7 @@ function minErr(module, ErrorConstructor) {
9263
9263
  return match;
9264
9264
  });
9265
9265
 
9266
- message = message + '\nhttp://errors.angularjs.org/1.3.0/' +
9266
+ message = message + '\nhttp://errors.angularjs.org/1.3.1/' +
9267
9267
  (module ? module + '/' : '') + code;
9268
9268
  for (i = 2; i < arguments.length; i++) {
9269
9269
  message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
@@ -9322,12 +9322,11 @@ function minErr(module, ErrorConstructor) {
9322
9322
  isBoolean: true,
9323
9323
  isPromiseLike: true,
9324
9324
  trim: true,
9325
+ escapeForRegexp: true,
9325
9326
  isElement: true,
9326
9327
  makeMap: true,
9327
- size: true,
9328
9328
  includes: true,
9329
9329
  arrayRemove: true,
9330
- isLeafNode: true,
9331
9330
  copy: true,
9332
9331
  shallowCopy: true,
9333
9332
  equals: true,
@@ -9397,7 +9396,7 @@ var VALIDITY_STATE_PROPERTY = 'validity';
9397
9396
  * @param {string} string String to be converted to lowercase.
9398
9397
  * @returns {string} Lowercased string.
9399
9398
  */
9400
- var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};
9399
+ var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
9401
9400
  var hasOwnProperty = Object.prototype.hasOwnProperty;
9402
9401
 
9403
9402
  /**
@@ -9410,7 +9409,7 @@ var hasOwnProperty = Object.prototype.hasOwnProperty;
9410
9409
  * @param {string} string String to be converted to uppercase.
9411
9410
  * @returns {string} Uppercased string.
9412
9411
  */
9413
- var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};
9412
+ var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};
9414
9413
 
9415
9414
 
9416
9415
  var manualLowercase = function(s) {
@@ -9493,6 +9492,11 @@ function isArrayLike(obj) {
9493
9492
  *
9494
9493
  * It is worth noting that `.forEach` does not iterate over inherited properties because it filters
9495
9494
  * using the `hasOwnProperty` method.
9495
+ *
9496
+ * Unlike ES262's
9497
+ * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),
9498
+ * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just
9499
+ * return the value provided.
9496
9500
  *
9497
9501
  ```js
9498
9502
  var values = {name: 'misko', gender: 'male'};
@@ -9541,18 +9545,12 @@ function forEach(obj, iterator, context) {
9541
9545
  }
9542
9546
 
9543
9547
  function sortedKeys(obj) {
9544
- var keys = [];
9545
- for (var key in obj) {
9546
- if (obj.hasOwnProperty(key)) {
9547
- keys.push(key);
9548
- }
9549
- }
9550
- return keys.sort();
9548
+ return Object.keys(obj).sort();
9551
9549
  }
9552
9550
 
9553
9551
  function forEachSorted(obj, iterator, context) {
9554
9552
  var keys = sortedKeys(obj);
9555
- for ( var i = 0; i < keys.length; i++) {
9553
+ for (var i = 0; i < keys.length; i++) {
9556
9554
  iterator.call(context, obj[keys[i]], keys[i]);
9557
9555
  }
9558
9556
  return keys;
@@ -9607,6 +9605,7 @@ function setHashKey(obj, h) {
9607
9605
  * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
9608
9606
  * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
9609
9607
  * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.
9608
+ * Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy).
9610
9609
  *
9611
9610
  * @param {Object} dst Destination object.
9612
9611
  * @param {...Object} src Source object(s).
@@ -9693,7 +9692,7 @@ function valueFn(value) {return function() {return value;};}
9693
9692
  * @param {*} value Reference to check.
9694
9693
  * @returns {boolean} True if `value` is undefined.
9695
9694
  */
9696
- function isUndefined(value){return typeof value === 'undefined';}
9695
+ function isUndefined(value) {return typeof value === 'undefined';}
9697
9696
 
9698
9697
 
9699
9698
  /**
@@ -9708,7 +9707,7 @@ function isUndefined(value){return typeof value === 'undefined';}
9708
9707
  * @param {*} value Reference to check.
9709
9708
  * @returns {boolean} True if `value` is defined.
9710
9709
  */
9711
- function isDefined(value){return typeof value !== 'undefined';}
9710
+ function isDefined(value) {return typeof value !== 'undefined';}
9712
9711
 
9713
9712
 
9714
9713
  /**
@@ -9724,7 +9723,7 @@ function isDefined(value){return typeof value !== 'undefined';}
9724
9723
  * @param {*} value Reference to check.
9725
9724
  * @returns {boolean} True if `value` is an `Object` but not `null`.
9726
9725
  */
9727
- function isObject(value){
9726
+ function isObject(value) {
9728
9727
  // http://jsperf.com/isobject4
9729
9728
  return value !== null && typeof value === 'object';
9730
9729
  }
@@ -9742,7 +9741,7 @@ function isObject(value){
9742
9741
  * @param {*} value Reference to check.
9743
9742
  * @returns {boolean} True if `value` is a `String`.
9744
9743
  */
9745
- function isString(value){return typeof value === 'string';}
9744
+ function isString(value) {return typeof value === 'string';}
9746
9745
 
9747
9746
 
9748
9747
  /**
@@ -9757,7 +9756,7 @@ function isString(value){return typeof value === 'string';}
9757
9756
  * @param {*} value Reference to check.
9758
9757
  * @returns {boolean} True if `value` is a `Number`.
9759
9758
  */
9760
- function isNumber(value){return typeof value === 'number';}
9759
+ function isNumber(value) {return typeof value === 'number';}
9761
9760
 
9762
9761
 
9763
9762
  /**
@@ -9803,7 +9802,7 @@ var isArray = Array.isArray;
9803
9802
  * @param {*} value Reference to check.
9804
9803
  * @returns {boolean} True if `value` is a `Function`.
9805
9804
  */
9806
- function isFunction(value){return typeof value === 'function';}
9805
+ function isFunction(value) {return typeof value === 'function';}
9807
9806
 
9808
9807
 
9809
9808
  /**
@@ -9859,6 +9858,14 @@ var trim = function(value) {
9859
9858
  return isString(value) ? value.trim() : value;
9860
9859
  };
9861
9860
 
9861
+ // Copied from:
9862
+ // http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021
9863
+ // Prereq: s is a string.
9864
+ var escapeForRegexp = function(s) {
9865
+ return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
9866
+ replace(/\x08/g, '\\x08');
9867
+ };
9868
+
9862
9869
 
9863
9870
  /**
9864
9871
  * @ngdoc function
@@ -9884,7 +9891,7 @@ function isElement(node) {
9884
9891
  */
9885
9892
  function makeMap(str) {
9886
9893
  var obj = {}, items = str.split(","), i;
9887
- for ( i = 0; i < items.length; i++ )
9894
+ for (i = 0; i < items.length; i++)
9888
9895
  obj[ items[i] ] = true;
9889
9896
  return obj;
9890
9897
  }
@@ -9894,34 +9901,6 @@ function nodeName_(element) {
9894
9901
  return lowercase(element.nodeName || element[0].nodeName);
9895
9902
  }
9896
9903
 
9897
-
9898
- /**
9899
- * @description
9900
- * Determines the number of elements in an array, the number of properties an object has, or
9901
- * the length of a string.
9902
- *
9903
- * Note: This function is used to augment the Object type in Angular expressions. See
9904
- * {@link angular.Object} for more information about Angular arrays.
9905
- *
9906
- * @param {Object|Array|string} obj Object, array, or string to inspect.
9907
- * @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object
9908
- * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.
9909
- */
9910
- function size(obj, ownPropsOnly) {
9911
- var count = 0, key;
9912
-
9913
- if (isArray(obj) || isString(obj)) {
9914
- return obj.length;
9915
- } else if (isObject(obj)) {
9916
- for (key in obj)
9917
- if (!ownPropsOnly || obj.hasOwnProperty(key))
9918
- count++;
9919
- }
9920
-
9921
- return count;
9922
- }
9923
-
9924
-
9925
9904
  function includes(array, obj) {
9926
9905
  return Array.prototype.indexOf.call(array, obj) != -1;
9927
9906
  }
@@ -9933,18 +9912,6 @@ function arrayRemove(array, value) {
9933
9912
  return value;
9934
9913
  }
9935
9914
 
9936
- function isLeafNode (node) {
9937
- if (node) {
9938
- switch (nodeName_(node)) {
9939
- case "option":
9940
- case "pre":
9941
- case "title":
9942
- return true;
9943
- }
9944
- }
9945
- return false;
9946
- }
9947
-
9948
9915
  /**
9949
9916
  * @ngdoc function
9950
9917
  * @name angular.copy
@@ -10042,7 +10009,7 @@ function copy(source, destination, stackSource, stackDest) {
10042
10009
  var result;
10043
10010
  if (isArray(source)) {
10044
10011
  destination.length = 0;
10045
- for ( var i = 0; i < source.length; i++) {
10012
+ for (var i = 0; i < source.length; i++) {
10046
10013
  result = copy(source[i], null, stackSource, stackDest);
10047
10014
  if (isObject(source[i])) {
10048
10015
  stackSource.push(source[i]);
@@ -10059,8 +10026,8 @@ function copy(source, destination, stackSource, stackDest) {
10059
10026
  delete destination[key];
10060
10027
  });
10061
10028
  }
10062
- for ( var key in source) {
10063
- if(source.hasOwnProperty(key)) {
10029
+ for (var key in source) {
10030
+ if (source.hasOwnProperty(key)) {
10064
10031
  result = copy(source[key], null, stackSource, stackDest);
10065
10032
  if (isObject(source[key])) {
10066
10033
  stackSource.push(source[key]);
@@ -10141,7 +10108,7 @@ function equals(o1, o2) {
10141
10108
  if (isArray(o1)) {
10142
10109
  if (!isArray(o2)) return false;
10143
10110
  if ((length = o1.length) == o2.length) {
10144
- for(key=0; key<length; key++) {
10111
+ for (key=0; key<length; key++) {
10145
10112
  if (!equals(o1[key], o2[key])) return false;
10146
10113
  }
10147
10114
  return true;
@@ -10154,12 +10121,12 @@ function equals(o1, o2) {
10154
10121
  } else {
10155
10122
  if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;
10156
10123
  keySet = {};
10157
- for(key in o1) {
10124
+ for (key in o1) {
10158
10125
  if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
10159
10126
  if (!equals(o1[key], o2[key])) return false;
10160
10127
  keySet[key] = true;
10161
10128
  }
10162
- for(key in o2) {
10129
+ for (key in o2) {
10163
10130
  if (!keySet.hasOwnProperty(key) &&
10164
10131
  key.charAt(0) !== '$' &&
10165
10132
  o2[key] !== undefined &&
@@ -10307,14 +10274,14 @@ function startingTag(element) {
10307
10274
  // turns out IE does not let you set .html() on elements which
10308
10275
  // are not allowed to have children. So we just ignore it.
10309
10276
  element.empty();
10310
- } catch(e) {}
10277
+ } catch (e) {}
10311
10278
  var elemHtml = jqLite('<div>').append(element).html();
10312
10279
  try {
10313
10280
  return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :
10314
10281
  elemHtml.
10315
10282
  match(/^(<[^>]+>)/)[1].
10316
10283
  replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
10317
- } catch(e) {
10284
+ } catch (e) {
10318
10285
  return lowercase(elemHtml);
10319
10286
  }
10320
10287
 
@@ -10334,7 +10301,7 @@ function startingTag(element) {
10334
10301
  function tryDecodeURIComponent(value) {
10335
10302
  try {
10336
10303
  return decodeURIComponent(value);
10337
- } catch(e) {
10304
+ } catch (e) {
10338
10305
  // Ignore any invalid uri component
10339
10306
  }
10340
10307
  }
@@ -10347,14 +10314,14 @@ function tryDecodeURIComponent(value) {
10347
10314
  function parseKeyValue(/**string*/keyValue) {
10348
10315
  var obj = {}, key_value, key;
10349
10316
  forEach((keyValue || "").split('&'), function(keyValue) {
10350
- if ( keyValue ) {
10317
+ if (keyValue) {
10351
10318
  key_value = keyValue.replace(/\+/g,'%20').split('=');
10352
10319
  key = tryDecodeURIComponent(key_value[0]);
10353
- if ( isDefined(key) ) {
10320
+ if (isDefined(key)) {
10354
10321
  var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
10355
10322
  if (!hasOwnProperty.call(obj, key)) {
10356
10323
  obj[key] = val;
10357
- } else if(isArray(obj[key])) {
10324
+ } else if (isArray(obj[key])) {
10358
10325
  obj[key].push(val);
10359
10326
  } else {
10360
10327
  obj[key] = [obj[key],val];
@@ -11191,7 +11158,7 @@ function setupModuleLoader(window) {
11191
11158
  config(configFn);
11192
11159
  }
11193
11160
 
11194
- return moduleInstance;
11161
+ return moduleInstance;
11195
11162
 
11196
11163
  /**
11197
11164
  * @param {string} provider
@@ -11314,15 +11281,15 @@ function setupModuleLoader(window) {
11314
11281
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
11315
11282
  */
11316
11283
  var version = {
11317
- full: '1.3.0', // all of these placeholder strings will be replaced by grunt's
11284
+ full: '1.3.1', // all of these placeholder strings will be replaced by grunt's
11318
11285
  major: 1, // package task
11319
11286
  minor: 3,
11320
- dot: 0,
11321
- codeName: 'superluminal-nudge'
11287
+ dot: 1,
11288
+ codeName: 'spectral-lobster'
11322
11289
  };
11323
11290
 
11324
11291
 
11325
- function publishExternalAPI(angular){
11292
+ function publishExternalAPI(angular) {
11326
11293
  extend(angular, {
11327
11294
  'bootstrap': bootstrap,
11328
11295
  'copy': copy,
@@ -11448,7 +11415,7 @@ function publishExternalAPI(angular){
11448
11415
  $timeout: $TimeoutProvider,
11449
11416
  $window: $WindowProvider,
11450
11417
  $$rAF: $$RAFProvider,
11451
- $$asyncCallback : $$AsyncCallbackProvider
11418
+ $$asyncCallback: $$AsyncCallbackProvider
11452
11419
  });
11453
11420
  }
11454
11421
  ]);
@@ -11498,7 +11465,7 @@ function publishExternalAPI(angular){
11498
11465
  * - [`children()`](http://api.jquery.com/children/) - Does not support selectors
11499
11466
  * - [`clone()`](http://api.jquery.com/clone/)
11500
11467
  * - [`contents()`](http://api.jquery.com/contents/)
11501
- * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyles()`
11468
+ * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`
11502
11469
  * - [`data()`](http://api.jquery.com/data/)
11503
11470
  * - [`detach()`](http://api.jquery.com/detach/)
11504
11471
  * - [`empty()`](http://api.jquery.com/empty/)
@@ -11576,7 +11543,7 @@ function jqNextId() { return ++jqId; }
11576
11543
 
11577
11544
  var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
11578
11545
  var MOZ_HACK_REGEXP = /^moz([A-Z])/;
11579
- var MOUSE_EVENT_MAP= { mouseleave : "mouseout", mouseenter : "mouseover"};
11546
+ var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"};
11580
11547
  var jqLiteMinErr = minErr('jqLite');
11581
11548
 
11582
11549
  /**
@@ -11705,7 +11672,7 @@ function jqLiteClone(element) {
11705
11672
  return element.cloneNode(true);
11706
11673
  }
11707
11674
 
11708
- function jqLiteDealoc(element, onlyDescendants){
11675
+ function jqLiteDealoc(element, onlyDescendants) {
11709
11676
  if (!onlyDescendants) jqLiteRemoveData(element);
11710
11677
 
11711
11678
  if (element.querySelectorAll) {
@@ -11812,7 +11779,7 @@ function jqLiteData(element, key, value) {
11812
11779
  function jqLiteHasClass(element, selector) {
11813
11780
  if (!element.getAttribute) return false;
11814
11781
  return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
11815
- indexOf( " " + selector + " " ) > -1);
11782
+ indexOf(" " + selector + " ") > -1);
11816
11783
  }
11817
11784
 
11818
11785
  function jqLiteRemoveClass(element, cssClasses) {
@@ -11871,13 +11838,13 @@ function jqLiteAddNodes(root, elements) {
11871
11838
 
11872
11839
 
11873
11840
  function jqLiteController(element, name) {
11874
- return jqLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');
11841
+ return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller');
11875
11842
  }
11876
11843
 
11877
11844
  function jqLiteInheritedData(element, name, value) {
11878
11845
  // if element is the document object work with the html element instead
11879
11846
  // this makes $(document).scope() possible
11880
- if(element.nodeType == NODE_TYPE_DOCUMENT) {
11847
+ if (element.nodeType == NODE_TYPE_DOCUMENT) {
11881
11848
  element = element.documentElement;
11882
11849
  }
11883
11850
  var names = isArray(name) ? name : [name];
@@ -11935,7 +11902,7 @@ var JQLitePrototype = JQLite.prototype = {
11935
11902
  }
11936
11903
 
11937
11904
  // check if document is already loaded
11938
- if (document.readyState === 'complete'){
11905
+ if (document.readyState === 'complete') {
11939
11906
  setTimeout(trigger);
11940
11907
  } else {
11941
11908
  this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
@@ -11943,12 +11910,11 @@ var JQLitePrototype = JQLite.prototype = {
11943
11910
  // jshint -W064
11944
11911
  JQLite(window).on('load', trigger); // fallback to window.onload for others
11945
11912
  // jshint +W064
11946
- this.on('DOMContentLoaded', trigger);
11947
11913
  }
11948
11914
  },
11949
11915
  toString: function() {
11950
11916
  var value = [];
11951
- forEach(this, function(e){ value.push('' + e);});
11917
+ forEach(this, function(e) { value.push('' + e);});
11952
11918
  return '[' + value.join(', ') + ']';
11953
11919
  },
11954
11920
 
@@ -11976,11 +11942,11 @@ forEach('input,select,option,textarea,button,form,details'.split(','), function(
11976
11942
  BOOLEAN_ELEMENTS[value] = true;
11977
11943
  });
11978
11944
  var ALIASED_ATTR = {
11979
- 'ngMinlength' : 'minlength',
11980
- 'ngMaxlength' : 'maxlength',
11981
- 'ngMin' : 'min',
11982
- 'ngMax' : 'max',
11983
- 'ngPattern' : 'pattern'
11945
+ 'ngMinlength': 'minlength',
11946
+ 'ngMaxlength': 'maxlength',
11947
+ 'ngMin': 'min',
11948
+ 'ngMax': 'max',
11949
+ 'ngPattern': 'pattern'
11984
11950
  };
11985
11951
 
11986
11952
  function getBooleanAttrName(element, name) {
@@ -12039,7 +12005,7 @@ forEach({
12039
12005
  }
12040
12006
  },
12041
12007
 
12042
- attr: function(element, name, value){
12008
+ attr: function(element, name, value) {
12043
12009
  var lowercasedName = lowercase(name);
12044
12010
  if (BOOLEAN_ATTR[lowercasedName]) {
12045
12011
  if (isDefined(value)) {
@@ -12092,7 +12058,7 @@ forEach({
12092
12058
  if (isUndefined(value)) {
12093
12059
  if (element.multiple && nodeName_(element) === 'select') {
12094
12060
  var result = [];
12095
- forEach(element.options, function (option) {
12061
+ forEach(element.options, function(option) {
12096
12062
  if (option.selected) {
12097
12063
  result.push(option.value || option.text);
12098
12064
  }
@@ -12113,7 +12079,7 @@ forEach({
12113
12079
  },
12114
12080
 
12115
12081
  empty: jqLiteEmpty
12116
- }, function(fn, name){
12082
+ }, function(fn, name) {
12117
12083
  /**
12118
12084
  * Properties: writes return selection, reads return first value
12119
12085
  */
@@ -12165,7 +12131,7 @@ forEach({
12165
12131
  });
12166
12132
 
12167
12133
  function createEventHandler(element, events) {
12168
- var eventHandler = function (event, type) {
12134
+ var eventHandler = function(event, type) {
12169
12135
  // jQuery specific api
12170
12136
  event.isDefaultPrevented = function() {
12171
12137
  return event.defaultPrevented;
@@ -12221,7 +12187,7 @@ function createEventHandler(element, events) {
12221
12187
  forEach({
12222
12188
  removeData: jqLiteRemoveData,
12223
12189
 
12224
- on: function jqLiteOn(element, type, fn, unsupported){
12190
+ on: function jqLiteOn(element, type, fn, unsupported) {
12225
12191
  if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
12226
12192
 
12227
12193
  // Do not add event handlers to non-elements because they will not be cleaned up.
@@ -12257,7 +12223,7 @@ forEach({
12257
12223
  var target = this, related = event.relatedTarget;
12258
12224
  // For mousenter/leave call the handler if related is outside the target.
12259
12225
  // NB: No relatedTarget if the mouse left/entered the browser window
12260
- if ( !related || (related !== target && !target.contains(related)) ){
12226
+ if (!related || (related !== target && !target.contains(related))) {
12261
12227
  handle(event, type);
12262
12228
  }
12263
12229
  });
@@ -12291,7 +12257,7 @@ forEach({
12291
12257
  replaceWith: function(element, replaceNode) {
12292
12258
  var index, parent = element.parentNode;
12293
12259
  jqLiteDealoc(element);
12294
- forEach(new JQLite(replaceNode), function(node){
12260
+ forEach(new JQLite(replaceNode), function(node) {
12295
12261
  if (index) {
12296
12262
  parent.insertBefore(node, index.nextSibling);
12297
12263
  } else {
@@ -12303,7 +12269,7 @@ forEach({
12303
12269
 
12304
12270
  children: function(element) {
12305
12271
  var children = [];
12306
- forEach(element.childNodes, function(element){
12272
+ forEach(element.childNodes, function(element) {
12307
12273
  if (element.nodeType === NODE_TYPE_ELEMENT)
12308
12274
  children.push(element);
12309
12275
  });
@@ -12329,7 +12295,7 @@ forEach({
12329
12295
  prepend: function(element, node) {
12330
12296
  if (element.nodeType === NODE_TYPE_ELEMENT) {
12331
12297
  var index = element.firstChild;
12332
- forEach(new JQLite(node), function(child){
12298
+ forEach(new JQLite(node), function(child) {
12333
12299
  element.insertBefore(child, index);
12334
12300
  });
12335
12301
  }
@@ -12366,7 +12332,7 @@ forEach({
12366
12332
 
12367
12333
  toggleClass: function(element, selector, condition) {
12368
12334
  if (selector) {
12369
- forEach(selector.split(' '), function(className){
12335
+ forEach(selector.split(' '), function(className) {
12370
12336
  var classCondition = condition;
12371
12337
  if (isUndefined(classCondition)) {
12372
12338
  classCondition = !jqLiteHasClass(element, className);
@@ -12431,14 +12397,14 @@ forEach({
12431
12397
  });
12432
12398
  }
12433
12399
  }
12434
- }, function(fn, name){
12400
+ }, function(fn, name) {
12435
12401
  /**
12436
12402
  * chaining functions
12437
12403
  */
12438
12404
  JQLite.prototype[name] = function(arg1, arg2, arg3) {
12439
12405
  var value;
12440
12406
 
12441
- for(var i = 0, ii = this.length; i < ii; i++) {
12407
+ for (var i = 0, ii = this.length; i < ii; i++) {
12442
12408
  if (isUndefined(value)) {
12443
12409
  value = fn(this[i], arg1, arg2, arg3);
12444
12410
  if (isDefined(value)) {
@@ -13235,7 +13201,7 @@ function createInjector(modulesToLoad, strictDi) {
13235
13201
  ////////////////////////////////////
13236
13202
  // Module Loading
13237
13203
  ////////////////////////////////////
13238
- function loadModules(modulesToLoad){
13204
+ function loadModules(modulesToLoad) {
13239
13205
  var runBlocks = [], moduleFn;
13240
13206
  forEach(modulesToLoad, function(module) {
13241
13207
  if (loadedModules.get(module)) return;
@@ -13243,7 +13209,7 @@ function createInjector(modulesToLoad, strictDi) {
13243
13209
 
13244
13210
  function runInvokeQueue(queue) {
13245
13211
  var i, ii;
13246
- for(i = 0, ii = queue.length; i < ii; i++) {
13212
+ for (i = 0, ii = queue.length; i < ii; i++) {
13247
13213
  var invokeArgs = queue[i],
13248
13214
  provider = providerInjector.get(invokeArgs[0]);
13249
13215
 
@@ -13323,7 +13289,7 @@ function createInjector(modulesToLoad, strictDi) {
13323
13289
  length, i,
13324
13290
  key;
13325
13291
 
13326
- for(i = 0, length = $inject.length; i < length; i++) {
13292
+ for (i = 0, length = $inject.length; i < length; i++) {
13327
13293
  key = $inject[i];
13328
13294
  if (typeof key !== 'string') {
13329
13295
  throw $injectorMinErr('itkn',
@@ -13539,7 +13505,6 @@ function $AnchorScrollProvider() {
13539
13505
  */
13540
13506
  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
13541
13507
  var document = $window.document;
13542
- var scrollScheduled = false;
13543
13508
 
13544
13509
  // Helper function to get first anchor from a NodeList
13545
13510
  // (using `Array#some()` instead of `angular#forEach()` since it's more performant
@@ -13713,7 +13678,7 @@ var $AnimateProvider = ['$provide', function($provide) {
13713
13678
  * @return {RegExp} The current CSS className expression value. If null then there is no expression value
13714
13679
  */
13715
13680
  this.classNameFilter = function(expression) {
13716
- if(arguments.length === 1) {
13681
+ if (arguments.length === 1) {
13717
13682
  this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
13718
13683
  }
13719
13684
  return this.$$classNameFilter;
@@ -13808,7 +13773,7 @@ var $AnimateProvider = ['$provide', function($provide) {
13808
13773
  * page}.
13809
13774
  */
13810
13775
  return {
13811
- animate : function(element, from, to) {
13776
+ animate: function(element, from, to) {
13812
13777
  applyStyles(element, { from: from, to: to });
13813
13778
  return asyncPromise();
13814
13779
  },
@@ -13829,7 +13794,7 @@ var $AnimateProvider = ['$provide', function($provide) {
13829
13794
  * @param {object=} options an optional collection of styles that will be applied to the element.
13830
13795
  * @return {Promise} the animation callback promise
13831
13796
  */
13832
- enter : function(element, parent, after, options) {
13797
+ enter: function(element, parent, after, options) {
13833
13798
  applyStyles(element, options);
13834
13799
  after ? after.after(element)
13835
13800
  : parent.prepend(element);
@@ -13847,7 +13812,7 @@ var $AnimateProvider = ['$provide', function($provide) {
13847
13812
  * @param {object=} options an optional collection of options that will be applied to the element.
13848
13813
  * @return {Promise} the animation callback promise
13849
13814
  */
13850
- leave : function(element, options) {
13815
+ leave: function(element, options) {
13851
13816
  element.remove();
13852
13817
  return asyncPromise();
13853
13818
  },
@@ -13870,7 +13835,7 @@ var $AnimateProvider = ['$provide', function($provide) {
13870
13835
  * @param {object=} options an optional collection of options that will be applied to the element.
13871
13836
  * @return {Promise} the animation callback promise
13872
13837
  */
13873
- move : function(element, parent, after, options) {
13838
+ move: function(element, parent, after, options) {
13874
13839
  // Do not remove element before insert. Removing will cause data associated with the
13875
13840
  // element to be dropped. Insert will implicitly do the remove.
13876
13841
  return this.enter(element, parent, after, options);
@@ -13889,16 +13854,16 @@ var $AnimateProvider = ['$provide', function($provide) {
13889
13854
  * @param {object=} options an optional collection of options that will be applied to the element.
13890
13855
  * @return {Promise} the animation callback promise
13891
13856
  */
13892
- addClass : function(element, className, options) {
13857
+ addClass: function(element, className, options) {
13893
13858
  return this.setClass(element, className, [], options);
13894
13859
  },
13895
13860
 
13896
- $$addClassImmediately : function(element, className, options) {
13861
+ $$addClassImmediately: function(element, className, options) {
13897
13862
  element = jqLite(element);
13898
13863
  className = !isString(className)
13899
13864
  ? (isArray(className) ? className.join(' ') : '')
13900
13865
  : className;
13901
- forEach(element, function (element) {
13866
+ forEach(element, function(element) {
13902
13867
  jqLiteAddClass(element, className);
13903
13868
  });
13904
13869
  applyStyles(element, options);
@@ -13918,16 +13883,16 @@ var $AnimateProvider = ['$provide', function($provide) {
13918
13883
  * @param {object=} options an optional collection of options that will be applied to the element.
13919
13884
  * @return {Promise} the animation callback promise
13920
13885
  */
13921
- removeClass : function(element, className, options) {
13886
+ removeClass: function(element, className, options) {
13922
13887
  return this.setClass(element, [], className, options);
13923
13888
  },
13924
13889
 
13925
- $$removeClassImmediately : function(element, className, options) {
13890
+ $$removeClassImmediately: function(element, className, options) {
13926
13891
  element = jqLite(element);
13927
13892
  className = !isString(className)
13928
13893
  ? (isArray(className) ? className.join(' ') : '')
13929
13894
  : className;
13930
- forEach(element, function (element) {
13895
+ forEach(element, function(element) {
13931
13896
  jqLiteRemoveClass(element, className);
13932
13897
  });
13933
13898
  applyStyles(element, options);
@@ -13948,7 +13913,7 @@ var $AnimateProvider = ['$provide', function($provide) {
13948
13913
  * @param {object=} options an optional collection of options that will be applied to the element.
13949
13914
  * @return {Promise} the animation callback promise
13950
13915
  */
13951
- setClass : function(element, add, remove, options) {
13916
+ setClass: function(element, add, remove, options) {
13952
13917
  var self = this;
13953
13918
  var STORAGE_KEY = '$$animateClasses';
13954
13919
  var createdCache = false;
@@ -13958,7 +13923,7 @@ var $AnimateProvider = ['$provide', function($provide) {
13958
13923
  if (!cache) {
13959
13924
  cache = {
13960
13925
  classes: {},
13961
- options : options
13926
+ options: options
13962
13927
  };
13963
13928
  createdCache = true;
13964
13929
  } else if (options && cache.options) {
@@ -13995,20 +13960,20 @@ var $AnimateProvider = ['$provide', function($provide) {
13995
13960
  return cache.promise;
13996
13961
  },
13997
13962
 
13998
- $$setClassImmediately : function(element, add, remove, options) {
13963
+ $$setClassImmediately: function(element, add, remove, options) {
13999
13964
  add && this.$$addClassImmediately(element, add);
14000
13965
  remove && this.$$removeClassImmediately(element, remove);
14001
13966
  applyStyles(element, options);
14002
13967
  return asyncPromise();
14003
13968
  },
14004
13969
 
14005
- enabled : noop,
14006
- cancel : noop
13970
+ enabled: noop,
13971
+ cancel: noop
14007
13972
  };
14008
13973
  }];
14009
13974
  }];
14010
13975
 
14011
- function $$AsyncCallbackProvider(){
13976
+ function $$AsyncCallbackProvider() {
14012
13977
  this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {
14013
13978
  return $$rAF.supported
14014
13979
  ? function(fn) { return $$rAF(fn); }
@@ -14070,7 +14035,7 @@ function Browser(window, document, $log, $sniffer) {
14070
14035
  } finally {
14071
14036
  outstandingRequestCount--;
14072
14037
  if (outstandingRequestCount === 0) {
14073
- while(outstandingRequestCallbacks.length) {
14038
+ while (outstandingRequestCallbacks.length) {
14074
14039
  try {
14075
14040
  outstandingRequestCallbacks.pop()();
14076
14041
  } catch (e) {
@@ -14091,7 +14056,7 @@ function Browser(window, document, $log, $sniffer) {
14091
14056
  // force browser to execute all pollFns - this is needed so that cookies and other pollers fire
14092
14057
  // at some deterministic time in respect to the test runner's actions. Leaving things up to the
14093
14058
  // regular poller would result in flaky tests.
14094
- forEach(pollFns, function(pollFn){ pollFn(); });
14059
+ forEach(pollFns, function(pollFn) { pollFn(); });
14095
14060
 
14096
14061
  if (outstandingRequestCount === 0) {
14097
14062
  callback();
@@ -14133,7 +14098,7 @@ function Browser(window, document, $log, $sniffer) {
14133
14098
  */
14134
14099
  function startPoller(interval, setTimeout) {
14135
14100
  (function check() {
14136
- forEach(pollFns, function(pollFn){ pollFn(); });
14101
+ forEach(pollFns, function(pollFn) { pollFn(); });
14137
14102
  pollTimeout = setTimeout(check, interval);
14138
14103
  })();
14139
14104
  }
@@ -14468,9 +14433,9 @@ function Browser(window, document, $log, $sniffer) {
14468
14433
 
14469
14434
  }
14470
14435
 
14471
- function $BrowserProvider(){
14436
+ function $BrowserProvider() {
14472
14437
  this.$get = ['$window', '$log', '$sniffer', '$document',
14473
- function( $window, $log, $sniffer, $document){
14438
+ function($window, $log, $sniffer, $document) {
14474
14439
  return new Browser($window, $document, $log, $sniffer);
14475
14440
  }];
14476
14441
  }
@@ -14844,7 +14809,8 @@ function $CacheFactoryProvider() {
14844
14809
  * ```
14845
14810
  *
14846
14811
  * **Note:** the `script` tag containing the template does not need to be included in the `head` of
14847
- * the document, but it must be below the `ng-app` definition.
14812
+ * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,
14813
+ * element with ng-app attribute), otherwise the template will be ignored.
14848
14814
  *
14849
14815
  * Adding via the $templateCache service:
14850
14816
  *
@@ -15038,7 +15004,9 @@ function $TemplateCacheProvider() {
15038
15004
  * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
15039
15005
  * in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent
15040
15006
  * scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You
15041
- * can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional.
15007
+ * can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If
15008
+ * you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use
15009
+ * `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).
15042
15010
  *
15043
15011
  * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
15044
15012
  * If no `attr` name is specified then the attribute name is assumed to be the same as the
@@ -15554,8 +15522,8 @@ $CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
15554
15522
  function $CompileProvider($provide, $$sanitizeUriProvider) {
15555
15523
  var hasDirectives = {},
15556
15524
  Suffix = 'Directive',
15557
- COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w_\-]+)\s+(.*)$/,
15558
- CLASS_DIRECTIVE_REGEXP = /(([\d\w_\-]+)(?:\:([^;]+))?;?)/,
15525
+ COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/,
15526
+ CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/,
15559
15527
  ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),
15560
15528
  REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/;
15561
15529
 
@@ -15565,7 +15533,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15565
15533
  var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
15566
15534
 
15567
15535
  function parseIsolateBindings(scope, directiveName) {
15568
- var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;
15536
+ var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/;
15569
15537
 
15570
15538
  var bindings = {};
15571
15539
 
@@ -15580,9 +15548,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15580
15548
  }
15581
15549
 
15582
15550
  bindings[scopeName] = {
15583
- attrName: match[3] || scopeName,
15584
- mode: match[1],
15585
- optional: match[2] === '?'
15551
+ mode: match[1][0],
15552
+ collection: match[2] === '*',
15553
+ optional: match[3] === '?',
15554
+ attrName: match[4] || scopeName
15586
15555
  };
15587
15556
  });
15588
15557
 
@@ -15728,7 +15697,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15728
15697
  */
15729
15698
  var debugInfoEnabled = true;
15730
15699
  this.debugInfoEnabled = function(enabled) {
15731
- if(isDefined(enabled)) {
15700
+ if (isDefined(enabled)) {
15732
15701
  debugInfoEnabled = enabled;
15733
15702
  return this;
15734
15703
  }
@@ -15772,8 +15741,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15772
15741
  *
15773
15742
  * @param {string} classVal The className value that will be added to the element
15774
15743
  */
15775
- $addClass : function(classVal) {
15776
- if(classVal && classVal.length > 0) {
15744
+ $addClass: function(classVal) {
15745
+ if (classVal && classVal.length > 0) {
15777
15746
  $animate.addClass(this.$$element, classVal);
15778
15747
  }
15779
15748
  },
@@ -15789,8 +15758,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15789
15758
  *
15790
15759
  * @param {string} classVal The className value that will be removed from the element
15791
15760
  */
15792
- $removeClass : function(classVal) {
15793
- if(classVal && classVal.length > 0) {
15761
+ $removeClass: function(classVal) {
15762
+ if (classVal && classVal.length > 0) {
15794
15763
  $animate.removeClass(this.$$element, classVal);
15795
15764
  }
15796
15765
  },
@@ -15807,7 +15776,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15807
15776
  * @param {string} newClasses The current CSS className value
15808
15777
  * @param {string} oldClasses The former CSS className value
15809
15778
  */
15810
- $updateClass : function(newClasses, oldClasses) {
15779
+ $updateClass: function(newClasses, oldClasses) {
15811
15780
  var toAdd = tokenDifference(newClasses, oldClasses);
15812
15781
  if (toAdd && toAdd.length) {
15813
15782
  $animate.addClass(this.$$element, toAdd);
@@ -15837,13 +15806,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15837
15806
  booleanKey = getBooleanAttrName(node, key),
15838
15807
  aliasedKey = getAliasedAttrName(node, key),
15839
15808
  observer = key,
15840
- normalizedVal,
15841
15809
  nodeName;
15842
15810
 
15843
15811
  if (booleanKey) {
15844
15812
  this.$$element.prop(key, value);
15845
15813
  attrName = booleanKey;
15846
- } else if(aliasedKey) {
15814
+ } else if (aliasedKey) {
15847
15815
  this[aliasedKey] = value;
15848
15816
  observer = aliasedKey;
15849
15817
  }
@@ -15884,9 +15852,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15884
15852
  for (var i=0; i<nbrUrisWith2parts; i++) {
15885
15853
  var innerIdx = i*2;
15886
15854
  // sanitize the uri
15887
- result += $$sanitizeUri(trim( rawUris[innerIdx]), true);
15855
+ result += $$sanitizeUri(trim(rawUris[innerIdx]), true);
15888
15856
  // add the descriptor
15889
- result += ( " " + trim(rawUris[innerIdx+1]));
15857
+ result += (" " + trim(rawUris[innerIdx+1]));
15890
15858
  }
15891
15859
 
15892
15860
  // split the last item into uri and descriptor
@@ -15896,7 +15864,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15896
15864
  result += $$sanitizeUri(trim(lastTuple[0]), true);
15897
15865
 
15898
15866
  // and add the last descriptor if any
15899
- if( lastTuple.length === 2) {
15867
+ if (lastTuple.length === 2) {
15900
15868
  result += (" " + trim(lastTuple[1]));
15901
15869
  }
15902
15870
  this[key] = value = result;
@@ -15947,7 +15915,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15947
15915
 
15948
15916
  listeners.push(fn);
15949
15917
  $rootScope.$evalAsync(function() {
15950
- if (!listeners.$$inter) {
15918
+ if (!listeners.$$inter && attrs.hasOwnProperty(key)) {
15951
15919
  // no one registered attribute interpolation function, so lets call it manually
15952
15920
  fn(attrs[key]);
15953
15921
  }
@@ -15963,7 +15931,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15963
15931
  function safeAddClass($element, className) {
15964
15932
  try {
15965
15933
  $element.addClass(className);
15966
- } catch(e) {
15934
+ } catch (e) {
15967
15935
  // ignore, since it means that we are trying to set class on
15968
15936
  // SVG element, where class name is read-only.
15969
15937
  }
@@ -16017,7 +15985,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16017
15985
  }
16018
15986
  // We can not compile top level text elements since text nodes can be merged and we will
16019
15987
  // not be able to attach scope data to them, so we will wrap them in <span>
16020
- forEach($compileNodes, function(node, index){
15988
+ forEach($compileNodes, function(node, index) {
16021
15989
  if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) {
16022
15990
  $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
16023
15991
  }
@@ -16027,7 +15995,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16027
15995
  maxPriority, ignoreDirective, previousCompileContext);
16028
15996
  compile.$$addScopeClass($compileNodes);
16029
15997
  var namespace = null;
16030
- return function publicLinkFn(scope, cloneConnectFn, transcludeControllers, parentBoundTranscludeFn, futureParentElement){
15998
+ return function publicLinkFn(scope, cloneConnectFn, transcludeControllers, parentBoundTranscludeFn, futureParentElement) {
16031
15999
  assertArg(scope, 'scope');
16032
16000
  if (!namespace) {
16033
16001
  namespace = detectNamespaceForChildElements(futureParentElement);
@@ -16152,7 +16120,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16152
16120
  stableNodeList = nodeList;
16153
16121
  }
16154
16122
 
16155
- for(i = 0, ii = linkFns.length; i < ii;) {
16123
+ for (i = 0, ii = linkFns.length; i < ii;) {
16156
16124
  node = stableNodeList[linkFns[i++]];
16157
16125
  nodeLinkFn = linkFns[i++];
16158
16126
  childLinkFn = linkFns[i++];
@@ -16165,7 +16133,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16165
16133
  childScope = scope;
16166
16134
  }
16167
16135
 
16168
- if ( nodeLinkFn.transcludeOnThisElement ) {
16136
+ if (nodeLinkFn.transcludeOnThisElement) {
16169
16137
  childBoundTranscludeFn = createBoundTranscludeFn(
16170
16138
  scope, nodeLinkFn.transclude, parentBoundTranscludeFn,
16171
16139
  nodeLinkFn.elementTranscludeOnThisElement);
@@ -16220,7 +16188,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16220
16188
  match,
16221
16189
  className;
16222
16190
 
16223
- switch(nodeType) {
16191
+ switch (nodeType) {
16224
16192
  case NODE_TYPE_ELEMENT: /* Element */
16225
16193
  // use the node name: <directive>
16226
16194
  addDirective(directives,
@@ -16312,7 +16280,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16312
16280
  var nodes = [];
16313
16281
  var depth = 0;
16314
16282
  if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {
16315
- var startNode = node;
16316
16283
  do {
16317
16284
  if (!node) {
16318
16285
  throw $compileMinErr('uterdir',
@@ -16396,7 +16363,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16396
16363
  directiveValue;
16397
16364
 
16398
16365
  // executes all directives on the current element
16399
- for(var i = 0, ii = directives.length; i < ii; i++) {
16366
+ for (var i = 0, ii = directives.length; i < ii; i++) {
16400
16367
  directive = directives[i];
16401
16368
  var attrStart = directive.$$start;
16402
16369
  var attrEnd = directive.$$end;
@@ -16640,7 +16607,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16640
16607
  "Controller '{0}', required by directive '{1}', can't be found!",
16641
16608
  require, directiveName);
16642
16609
  }
16643
- return value;
16610
+ return value || null;
16644
16611
  } else if (isArray(require)) {
16645
16612
  value = [];
16646
16613
  forEach(require, function(require) {
@@ -16702,8 +16669,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16702
16669
  }
16703
16670
 
16704
16671
  if (newIsolateScopeDirective) {
16705
- var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;
16706
-
16707
16672
  compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||
16708
16673
  templateDirective === newIsolateScopeDirective.$$originalDirective)));
16709
16674
  compile.$$addScopeClass($element, true);
@@ -16729,7 +16694,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16729
16694
  isolateBindingContext[scopeName] = value;
16730
16695
  });
16731
16696
  attrs.$$observers[attrName].$$scope = scope;
16732
- if( attrs[attrName] ) {
16697
+ if (attrs[attrName]) {
16733
16698
  // If the attribute has been provided then we trigger an interpolation to ensure
16734
16699
  // the value is there for use in the link fn
16735
16700
  isolateBindingContext[scopeName] = $interpolate(attrs[attrName])(scope);
@@ -16744,7 +16709,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16744
16709
  if (parentGet.literal) {
16745
16710
  compare = equals;
16746
16711
  } else {
16747
- compare = function(a,b) { return a === b || (a !== a && b !== b); };
16712
+ compare = function(a, b) { return a === b || (a !== a && b !== b); };
16748
16713
  }
16749
16714
  parentSet = parentGet.assign || function() {
16750
16715
  // reset the change, or we will throw this exception on every $digest
@@ -16768,7 +16733,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16768
16733
  return lastValue = parentValue;
16769
16734
  };
16770
16735
  parentValueWatch.$stateful = true;
16771
- var unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
16736
+ var unwatch;
16737
+ if (definition.collection) {
16738
+ unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
16739
+ } else {
16740
+ unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
16741
+ }
16772
16742
  isolateScope.$on('$destroy', unwatch);
16773
16743
  break;
16774
16744
 
@@ -16789,7 +16759,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16789
16759
  }
16790
16760
 
16791
16761
  // PRELINKING
16792
- for(i = 0, ii = preLinkFns.length; i < ii; i++) {
16762
+ for (i = 0, ii = preLinkFns.length; i < ii; i++) {
16793
16763
  linkFn = preLinkFns[i];
16794
16764
  invokeLinkFn(linkFn,
16795
16765
  linkFn.isolateScope ? isolateScope : scope,
@@ -16810,7 +16780,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16810
16780
  childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);
16811
16781
 
16812
16782
  // POSTLINKING
16813
- for(i = postLinkFns.length - 1; i >= 0; i--) {
16783
+ for (i = postLinkFns.length - 1; i >= 0; i--) {
16814
16784
  linkFn = postLinkFns[i];
16815
16785
  invokeLinkFn(linkFn,
16816
16786
  linkFn.isolateScope ? isolateScope : scope,
@@ -16870,11 +16840,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16870
16840
  if (name === ignoreDirective) return null;
16871
16841
  var match = null;
16872
16842
  if (hasDirectives.hasOwnProperty(name)) {
16873
- for(var directive, directives = $injector.get(name + Suffix),
16843
+ for (var directive, directives = $injector.get(name + Suffix),
16874
16844
  i = 0, ii = directives.length; i<ii; i++) {
16875
16845
  try {
16876
16846
  directive = directives[i];
16877
- if ( (maxPriority === undefined || maxPriority > directive.priority) &&
16847
+ if ((maxPriority === undefined || maxPriority > directive.priority) &&
16878
16848
  directive.restrict.indexOf(location) != -1) {
16879
16849
  if (startAttrName) {
16880
16850
  directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
@@ -16882,7 +16852,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16882
16852
  tDirectives.push(directive);
16883
16853
  match = directive;
16884
16854
  }
16885
- } catch(e) { $exceptionHandler(e); }
16855
+ } catch (e) { $exceptionHandler(e); }
16886
16856
  }
16887
16857
  }
16888
16858
  return match;
@@ -16899,7 +16869,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16899
16869
  */
16900
16870
  function directiveIsMultiElement(name) {
16901
16871
  if (hasDirectives.hasOwnProperty(name)) {
16902
- for(var directive, directives = $injector.get(name + Suffix),
16872
+ for (var directive, directives = $injector.get(name + Suffix),
16903
16873
  i = 0, ii = directives.length; i<ii; i++) {
16904
16874
  directive = directives[i];
16905
16875
  if (directive.multiElement) {
@@ -17016,7 +16986,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17016
16986
  });
17017
16987
  afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
17018
16988
 
17019
- while(linkQueue.length) {
16989
+ while (linkQueue.length) {
17020
16990
  var scope = linkQueue.shift(),
17021
16991
  beforeTemplateLinkNode = linkQueue.shift(),
17022
16992
  linkRootElement = linkQueue.shift(),
@@ -17115,7 +17085,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17115
17085
 
17116
17086
  function wrapTemplate(type, template) {
17117
17087
  type = lowercase(type || 'html');
17118
- switch(type) {
17088
+ switch (type) {
17119
17089
  case 'svg':
17120
17090
  case 'math':
17121
17091
  var wrapper = document.createElement('div');
@@ -17196,7 +17166,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17196
17166
  //skip animations when the first digest occurs (when
17197
17167
  //both the new and the old values are the same) since
17198
17168
  //the CSS classes are the non-interpolated values
17199
- if(name === 'class' && newValue != oldValue) {
17169
+ if (name === 'class' && newValue != oldValue) {
17200
17170
  attr.$updateClass(newValue, oldValue);
17201
17171
  } else {
17202
17172
  attr.$set(name, newValue);
@@ -17226,7 +17196,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17226
17196
  i, ii;
17227
17197
 
17228
17198
  if ($rootElement) {
17229
- for(i = 0, ii = $rootElement.length; i < ii; i++) {
17199
+ for (i = 0, ii = $rootElement.length; i < ii; i++) {
17230
17200
  if ($rootElement[i] == firstElementToRemove) {
17231
17201
  $rootElement[i++] = newNode;
17232
17202
  for (var j = i, j2 = j + removeCount - 1,
@@ -17301,14 +17271,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17301
17271
  function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {
17302
17272
  try {
17303
17273
  linkFn(scope, $element, attrs, controllers, transcludeFn);
17304
- } catch(e) {
17274
+ } catch (e) {
17305
17275
  $exceptionHandler(e, startingTag($element));
17306
17276
  }
17307
17277
  }
17308
17278
  }];
17309
17279
  }
17310
17280
 
17311
- var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i;
17281
+ var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i;
17312
17282
  /**
17313
17283
  * Converts all accepted directives format into proper directive name.
17314
17284
  * All of these will become 'myDirective':
@@ -17374,7 +17344,7 @@ function nodesetLinkingFn(
17374
17344
  /* NodeList */ nodeList,
17375
17345
  /* Element */ rootElement,
17376
17346
  /* function(Function) */ boundTranscludeFn
17377
- ){}
17347
+ ) {}
17378
17348
 
17379
17349
  function directiveLinkingFn(
17380
17350
  /* nodesetLinkingFn */ nodesetLinkingFn,
@@ -17382,7 +17352,7 @@ function directiveLinkingFn(
17382
17352
  /* Node */ node,
17383
17353
  /* Element */ rootElement,
17384
17354
  /* function(Function) */ boundTranscludeFn
17385
- ){}
17355
+ ) {}
17386
17356
 
17387
17357
  function tokenDifference(str1, str2) {
17388
17358
  var values = '',
@@ -17390,10 +17360,10 @@ function tokenDifference(str1, str2) {
17390
17360
  tokens2 = str2.split(/\s+/);
17391
17361
 
17392
17362
  outer:
17393
- for(var i = 0; i < tokens1.length; i++) {
17363
+ for (var i = 0; i < tokens1.length; i++) {
17394
17364
  var token = tokens1[i];
17395
- for(var j = 0; j < tokens2.length; j++) {
17396
- if(token == tokens2[j]) continue outer;
17365
+ for (var j = 0; j < tokens2.length; j++) {
17366
+ if (token == tokens2[j]) continue outer;
17397
17367
  }
17398
17368
  values += (values.length > 0 ? ' ' : '') + token;
17399
17369
  }
@@ -17499,7 +17469,7 @@ function $ControllerProvider() {
17499
17469
  identifier = ident;
17500
17470
  }
17501
17471
 
17502
- if(isString(expression)) {
17472
+ if (isString(expression)) {
17503
17473
  match = expression.match(CNTRL_REG),
17504
17474
  constructor = match[1],
17505
17475
  identifier = identifier || match[3];
@@ -17585,8 +17555,8 @@ function $ControllerProvider() {
17585
17555
  </file>
17586
17556
  </example>
17587
17557
  */
17588
- function $DocumentProvider(){
17589
- this.$get = ['$window', function(window){
17558
+ function $DocumentProvider() {
17559
+ this.$get = ['$window', function(window) {
17590
17560
  return jqLite(window.document);
17591
17561
  }];
17592
17562
  }
@@ -17607,8 +17577,8 @@ function $DocumentProvider(){
17607
17577
  * ## Example:
17608
17578
  *
17609
17579
  * ```js
17610
- * angular.module('exceptionOverride', []).factory('$exceptionHandler', function () {
17611
- * return function (exception, cause) {
17580
+ * angular.module('exceptionOverride', []).factory('$exceptionHandler', function() {
17581
+ * return function(exception, cause) {
17612
17582
  * exception.message += ' (caused by "' + cause + '")';
17613
17583
  * throw exception;
17614
17584
  * };
@@ -17639,6 +17609,25 @@ function $ExceptionHandlerProvider() {
17639
17609
  }];
17640
17610
  }
17641
17611
 
17612
+ var APPLICATION_JSON = 'application/json';
17613
+ var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};
17614
+ var JSON_START = /^\s*(\[|\{[^\{])/;
17615
+ var JSON_END = /[\}\]]\s*$/;
17616
+ var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/;
17617
+
17618
+ function defaultHttpResponseTransform(data, headers) {
17619
+ if (isString(data)) {
17620
+ // strip json vulnerability protection prefix
17621
+ data = data.replace(JSON_PROTECTION_PREFIX, '');
17622
+ var contentType = headers('Content-Type');
17623
+ if ((contentType && contentType.indexOf(APPLICATION_JSON) === 0) ||
17624
+ (JSON_START.test(data) && JSON_END.test(data))) {
17625
+ data = fromJson(data);
17626
+ }
17627
+ }
17628
+ return data;
17629
+ }
17630
+
17642
17631
  /**
17643
17632
  * Parse headers into key value object
17644
17633
  *
@@ -17725,12 +17714,6 @@ function isSuccess(status) {
17725
17714
  * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
17726
17715
  * */
17727
17716
  function $HttpProvider() {
17728
- var JSON_START = /^\s*(\[|\{[^\{])/,
17729
- JSON_END = /[\}\]]\s*$/,
17730
- PROTECTION_PREFIX = /^\)\]\}',?\n/,
17731
- APPLICATION_JSON = 'application/json',
17732
- CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};
17733
-
17734
17717
  /**
17735
17718
  * @ngdoc property
17736
17719
  * @name $httpProvider#defaults
@@ -17754,18 +17737,7 @@ function $HttpProvider() {
17754
17737
  **/
17755
17738
  var defaults = this.defaults = {
17756
17739
  // transform incoming response data
17757
- transformResponse: [function defaultHttpResponseTransform(data, headers) {
17758
- if (isString(data)) {
17759
- // strip json vulnerability protection prefix
17760
- data = data.replace(PROTECTION_PREFIX, '');
17761
- var contentType = headers('Content-Type');
17762
- if ((contentType && contentType.indexOf(APPLICATION_JSON) === 0) ||
17763
- (JSON_START.test(data) && JSON_END.test(data))) {
17764
- data = fromJson(data);
17765
- }
17766
- }
17767
- return data;
17768
- }],
17740
+ transformResponse: [defaultHttpResponseTransform],
17769
17741
 
17770
17742
  // transform outgoing request data
17771
17743
  transformRequest: [function(d) {
@@ -17815,9 +17787,18 @@ function $HttpProvider() {
17815
17787
  };
17816
17788
 
17817
17789
  /**
17818
- * Are ordered by request, i.e. they are applied in the same order as the
17790
+ * @ngdoc property
17791
+ * @name $httpProvider#interceptors
17792
+ * @description
17793
+ *
17794
+ * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}
17795
+ * pre-processing of request or postprocessing of responses.
17796
+ *
17797
+ * These service factories are ordered by request, i.e. they are applied in the same order as the
17819
17798
  * array, on request, but reverse order, on response.
17820
- */
17799
+ *
17800
+ * {@link ng.$http#interceptors Interceptors detailed info}
17801
+ **/
17821
17802
  var interceptorFactories = this.interceptors = [];
17822
17803
 
17823
17804
  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',
@@ -18384,7 +18365,7 @@ function $HttpProvider() {
18384
18365
  }
18385
18366
  });
18386
18367
 
18387
- while(chain.length) {
18368
+ while (chain.length) {
18388
18369
  var thenFn = chain.shift();
18389
18370
  var rejectFn = chain.shift();
18390
18371
 
@@ -18699,7 +18680,7 @@ function $HttpProvider() {
18699
18680
  status: status,
18700
18681
  headers: headersGetter(headers),
18701
18682
  config: config,
18702
- statusText : statusText
18683
+ statusText: statusText
18703
18684
  });
18704
18685
  }
18705
18686
 
@@ -18720,7 +18701,7 @@ function $HttpProvider() {
18720
18701
 
18721
18702
  forEach(value, function(v) {
18722
18703
  if (isObject(v)) {
18723
- if (isDate(v)){
18704
+ if (isDate(v)) {
18724
18705
  v = v.toISOString();
18725
18706
  } else {
18726
18707
  v = toJson(v);
@@ -18730,7 +18711,7 @@ function $HttpProvider() {
18730
18711
  encodeUriQuery(v));
18731
18712
  });
18732
18713
  });
18733
- if(parts.length > 0) {
18714
+ if (parts.length > 0) {
18734
18715
  url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
18735
18716
  }
18736
18717
  return url;
@@ -18817,7 +18798,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
18817
18798
  statusText);
18818
18799
  };
18819
18800
 
18820
- var requestError = function () {
18801
+ var requestError = function() {
18821
18802
  // The response is always empty
18822
18803
  // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error
18823
18804
  completeRequest(callback, -1, null, null, '');
@@ -18959,7 +18940,7 @@ function $InterpolateProvider() {
18959
18940
  * @param {string=} value new value to set the starting symbol to.
18960
18941
  * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
18961
18942
  */
18962
- this.startSymbol = function(value){
18943
+ this.startSymbol = function(value) {
18963
18944
  if (value) {
18964
18945
  startSymbol = value;
18965
18946
  return this;
@@ -18977,7 +18958,7 @@ function $InterpolateProvider() {
18977
18958
  * @param {string=} value new value to set the ending symbol to.
18978
18959
  * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
18979
18960
  */
18980
- this.endSymbol = function(value){
18961
+ this.endSymbol = function(value) {
18981
18962
  if (value) {
18982
18963
  endSymbol = value;
18983
18964
  return this;
@@ -19103,9 +19084,9 @@ function $InterpolateProvider() {
19103
19084
  concat = [],
19104
19085
  expressionPositions = [];
19105
19086
 
19106
- while(index < textLength) {
19107
- if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&
19108
- ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {
19087
+ while (index < textLength) {
19088
+ if (((startIndex = text.indexOf(startSymbol, index)) != -1) &&
19089
+ ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) {
19109
19090
  if (index !== startIndex) {
19110
19091
  concat.push(unescapeText(text.substring(index, startIndex)));
19111
19092
  }
@@ -19139,20 +19120,20 @@ function $InterpolateProvider() {
19139
19120
 
19140
19121
  if (!mustHaveExpression || expressions.length) {
19141
19122
  var compute = function(values) {
19142
- for(var i = 0, ii = expressions.length; i < ii; i++) {
19123
+ for (var i = 0, ii = expressions.length; i < ii; i++) {
19143
19124
  if (allOrNothing && isUndefined(values[i])) return;
19144
19125
  concat[expressionPositions[i]] = values[i];
19145
19126
  }
19146
19127
  return concat.join('');
19147
19128
  };
19148
19129
 
19149
- var getValue = function (value) {
19130
+ var getValue = function(value) {
19150
19131
  return trustedContext ?
19151
19132
  $sce.getTrusted(trustedContext, value) :
19152
19133
  $sce.valueOf(value);
19153
19134
  };
19154
19135
 
19155
- var stringify = function (value) {
19136
+ var stringify = function(value) {
19156
19137
  if (value == null) { // null || undefined
19157
19138
  return '';
19158
19139
  }
@@ -19180,7 +19161,7 @@ function $InterpolateProvider() {
19180
19161
  }
19181
19162
 
19182
19163
  return compute(values);
19183
- } catch(err) {
19164
+ } catch (err) {
19184
19165
  var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
19185
19166
  err.toString());
19186
19167
  $exceptionHandler(newErr);
@@ -19190,7 +19171,7 @@ function $InterpolateProvider() {
19190
19171
  // all of these properties are undocumented for now
19191
19172
  exp: text, //just for compatibility with regular watchers created via $watch
19192
19173
  expressions: expressions,
19193
- $$watchDelegate: function (scope, listener, objectEquality) {
19174
+ $$watchDelegate: function(scope, listener, objectEquality) {
19194
19175
  var lastValue;
19195
19176
  return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {
19196
19177
  var currValue = compute(values);
@@ -19211,7 +19192,7 @@ function $InterpolateProvider() {
19211
19192
  function parseStringifyInterceptor(value) {
19212
19193
  try {
19213
19194
  return stringify(getValue(value));
19214
- } catch(err) {
19195
+ } catch (err) {
19215
19196
  var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
19216
19197
  err.toString());
19217
19198
  $exceptionHandler(newErr);
@@ -19450,7 +19431,7 @@ function $IntervalProvider() {
19450
19431
  *
19451
19432
  * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)
19452
19433
  */
19453
- function $LocaleProvider(){
19434
+ function $LocaleProvider() {
19454
19435
  this.$get = function() {
19455
19436
  return {
19456
19437
  id: 'en-us',
@@ -19493,7 +19474,7 @@ function $LocaleProvider(){
19493
19474
  SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),
19494
19475
  AMPMS: ['AM','PM'],
19495
19476
  medium: 'MMM d, y h:mm:ss a',
19496
- short: 'M/d/yy h:mm a',
19477
+ 'short': 'M/d/yy h:mm a',
19497
19478
  fullDate: 'EEEE, MMMM d, y',
19498
19479
  longDate: 'MMMM d, y',
19499
19480
  mediumDate: 'MMM d, y',
@@ -19608,7 +19589,7 @@ function LocationHtml5Url(appBase, basePrefix) {
19608
19589
 
19609
19590
  /**
19610
19591
  * Parse given html5 (regular) url string into properties
19611
- * @param {string} newAbsoluteUrl HTML5 url
19592
+ * @param {string} url HTML5 url
19612
19593
  * @private
19613
19594
  */
19614
19595
  this.$$parse = function(url) {
@@ -19649,14 +19630,14 @@ function LocationHtml5Url(appBase, basePrefix) {
19649
19630
  var appUrl, prevAppUrl;
19650
19631
  var rewrittenUrl;
19651
19632
 
19652
- if ( (appUrl = beginsWith(appBase, url)) !== undefined ) {
19633
+ if ((appUrl = beginsWith(appBase, url)) !== undefined) {
19653
19634
  prevAppUrl = appUrl;
19654
- if ( (appUrl = beginsWith(basePrefix, appUrl)) !== undefined ) {
19635
+ if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) {
19655
19636
  rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
19656
19637
  } else {
19657
19638
  rewrittenUrl = appBase + prevAppUrl;
19658
19639
  }
19659
- } else if ( (appUrl = beginsWith(appBaseNoFile, url)) !== undefined ) {
19640
+ } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) {
19660
19641
  rewrittenUrl = appBaseNoFile + appUrl;
19661
19642
  } else if (appBaseNoFile == url + '/') {
19662
19643
  rewrittenUrl = appBaseNoFile;
@@ -19718,7 +19699,7 @@ function LocationHashbangUrl(appBase, hashPrefix) {
19718
19699
  * Inside of Angular, we're always using pathnames that
19719
19700
  * do not include drive names for routing.
19720
19701
  */
19721
- function removeWindowsDriveName (path, url, base) {
19702
+ function removeWindowsDriveName(path, url, base) {
19722
19703
  /*
19723
19704
  Matches paths for file protocol on windows,
19724
19705
  such as /C:/foo/bar, and captures only /foo/bar.
@@ -19755,7 +19736,7 @@ function LocationHashbangUrl(appBase, hashPrefix) {
19755
19736
  };
19756
19737
 
19757
19738
  this.$$parseLinkUrl = function(url, relHref) {
19758
- if(stripHash(appBase) == stripHash(url)) {
19739
+ if (stripHash(appBase) == stripHash(url)) {
19759
19740
  this.$$parse(url);
19760
19741
  return true;
19761
19742
  }
@@ -19790,11 +19771,11 @@ function LocationHashbangInHtml5Url(appBase, hashPrefix) {
19790
19771
  var rewrittenUrl;
19791
19772
  var appUrl;
19792
19773
 
19793
- if ( appBase == stripHash(url) ) {
19774
+ if (appBase == stripHash(url)) {
19794
19775
  rewrittenUrl = url;
19795
- } else if ( (appUrl = beginsWith(appBaseNoFile, url)) ) {
19776
+ } else if ((appUrl = beginsWith(appBaseNoFile, url))) {
19796
19777
  rewrittenUrl = appBase + hashPrefix + appUrl;
19797
- } else if ( appBaseNoFile === url + '/') {
19778
+ } else if (appBaseNoFile === url + '/') {
19798
19779
  rewrittenUrl = appBaseNoFile;
19799
19780
  }
19800
19781
  if (rewrittenUrl) {
@@ -20041,7 +20022,7 @@ var locationPrototype = {
20041
20022
  }
20042
20023
  };
20043
20024
 
20044
- forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function (Location) {
20025
+ forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) {
20045
20026
  Location.prototype = Object.create(locationPrototype);
20046
20027
 
20047
20028
  /**
@@ -20133,7 +20114,7 @@ function locationGetterSetter(property, preprocess) {
20133
20114
  * @description
20134
20115
  * Use the `$locationProvider` to configure how the application deep linking paths are stored.
20135
20116
  */
20136
- function $LocationProvider(){
20117
+ function $LocationProvider() {
20137
20118
  var hashPrefix = '',
20138
20119
  html5Mode = {
20139
20120
  enabled: false,
@@ -20240,7 +20221,7 @@ function $LocationProvider(){
20240
20221
  */
20241
20222
 
20242
20223
  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',
20243
- function( $rootScope, $browser, $sniffer, $rootElement) {
20224
+ function($rootScope, $browser, $sniffer, $rootElement) {
20244
20225
  var $location,
20245
20226
  LocationMode,
20246
20227
  baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
@@ -20441,7 +20422,7 @@ function $LocationProvider(){
20441
20422
  * @description
20442
20423
  * Use the `$logProvider` to configure how the application logs messages
20443
20424
  */
20444
- function $LogProvider(){
20425
+ function $LogProvider() {
20445
20426
  var debug = true,
20446
20427
  self = this;
20447
20428
 
@@ -20461,7 +20442,7 @@ function $LogProvider(){
20461
20442
  }
20462
20443
  };
20463
20444
 
20464
- this.$get = ['$window', function($window){
20445
+ this.$get = ['$window', function($window) {
20465
20446
  return {
20466
20447
  /**
20467
20448
  * @ngdoc method
@@ -20506,7 +20487,7 @@ function $LogProvider(){
20506
20487
  * @description
20507
20488
  * Write a debug message
20508
20489
  */
20509
- debug: (function () {
20490
+ debug: (function() {
20510
20491
  var fn = consoleLog('debug');
20511
20492
 
20512
20493
  return function() {
@@ -20659,7 +20640,7 @@ CONSTANTS['this'].sharedGetter = true;
20659
20640
 
20660
20641
  //Operators - will be wrapped by binaryFn/unaryFn/assignment/filter
20661
20642
  var OPERATORS = extend(createMap(), {
20662
- '+':function(self, locals, a,b){
20643
+ '+':function(self, locals, a, b) {
20663
20644
  a=a(self, locals); b=b(self, locals);
20664
20645
  if (isDefined(a)) {
20665
20646
  if (isDefined(b)) {
@@ -20668,24 +20649,24 @@ var OPERATORS = extend(createMap(), {
20668
20649
  return a;
20669
20650
  }
20670
20651
  return isDefined(b)?b:undefined;},
20671
- '-':function(self, locals, a,b){
20652
+ '-':function(self, locals, a, b) {
20672
20653
  a=a(self, locals); b=b(self, locals);
20673
20654
  return (isDefined(a)?a:0)-(isDefined(b)?b:0);
20674
20655
  },
20675
- '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},
20676
- '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},
20677
- '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},
20678
- '===':function(self, locals, a, b){return a(self, locals)===b(self, locals);},
20679
- '!==':function(self, locals, a, b){return a(self, locals)!==b(self, locals);},
20680
- '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},
20681
- '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},
20682
- '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},
20683
- '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},
20684
- '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},
20685
- '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},
20686
- '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},
20687
- '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},
20688
- '!':function(self, locals, a){return !a(self, locals);},
20656
+ '*':function(self, locals, a, b) {return a(self, locals)*b(self, locals);},
20657
+ '/':function(self, locals, a, b) {return a(self, locals)/b(self, locals);},
20658
+ '%':function(self, locals, a, b) {return a(self, locals)%b(self, locals);},
20659
+ '===':function(self, locals, a, b) {return a(self, locals)===b(self, locals);},
20660
+ '!==':function(self, locals, a, b) {return a(self, locals)!==b(self, locals);},
20661
+ '==':function(self, locals, a, b) {return a(self, locals)==b(self, locals);},
20662
+ '!=':function(self, locals, a, b) {return a(self, locals)!=b(self, locals);},
20663
+ '<':function(self, locals, a, b) {return a(self, locals)<b(self, locals);},
20664
+ '>':function(self, locals, a, b) {return a(self, locals)>b(self, locals);},
20665
+ '<=':function(self, locals, a, b) {return a(self, locals)<=b(self, locals);},
20666
+ '>=':function(self, locals, a, b) {return a(self, locals)>=b(self, locals);},
20667
+ '&&':function(self, locals, a, b) {return a(self, locals)&&b(self, locals);},
20668
+ '||':function(self, locals, a, b) {return a(self, locals)||b(self, locals);},
20669
+ '!':function(self, locals, a) {return !a(self, locals);},
20689
20670
 
20690
20671
  //Tokenized as operators but parsed as assignment/filters
20691
20672
  '=':true,
@@ -20700,14 +20681,14 @@ var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'
20700
20681
  /**
20701
20682
  * @constructor
20702
20683
  */
20703
- var Lexer = function (options) {
20684
+ var Lexer = function(options) {
20704
20685
  this.options = options;
20705
20686
  };
20706
20687
 
20707
20688
  Lexer.prototype = {
20708
20689
  constructor: Lexer,
20709
20690
 
20710
- lex: function (text) {
20691
+ lex: function(text) {
20711
20692
  this.text = text;
20712
20693
  this.index = 0;
20713
20694
  this.ch = undefined;
@@ -20944,13 +20925,13 @@ function isConstant(exp) {
20944
20925
  /**
20945
20926
  * @constructor
20946
20927
  */
20947
- var Parser = function (lexer, $filter, options) {
20928
+ var Parser = function(lexer, $filter, options) {
20948
20929
  this.lexer = lexer;
20949
20930
  this.$filter = $filter;
20950
20931
  this.options = options;
20951
20932
  };
20952
20933
 
20953
- Parser.ZERO = extend(function () {
20934
+ Parser.ZERO = extend(function() {
20954
20935
  return 0;
20955
20936
  }, {
20956
20937
  sharedGetter: true,
@@ -20960,7 +20941,7 @@ Parser.ZERO = extend(function () {
20960
20941
  Parser.prototype = {
20961
20942
  constructor: Parser,
20962
20943
 
20963
- parse: function (text) {
20944
+ parse: function(text) {
20964
20945
  this.text = text;
20965
20946
  this.tokens = this.lexer.lex(text);
20966
20947
 
@@ -20976,7 +20957,7 @@ Parser.prototype = {
20976
20957
  return value;
20977
20958
  },
20978
20959
 
20979
- primary: function () {
20960
+ primary: function() {
20980
20961
  var primary;
20981
20962
  if (this.expect('(')) {
20982
20963
  primary = this.filterChain();
@@ -21039,7 +21020,7 @@ Parser.prototype = {
21039
21020
  return false;
21040
21021
  },
21041
21022
 
21042
- expect: function(e1, e2, e3, e4){
21023
+ expect: function(e1, e2, e3, e4) {
21043
21024
  var token = this.peek(e1, e2, e3, e4);
21044
21025
  if (token) {
21045
21026
  this.tokens.shift();
@@ -21048,7 +21029,7 @@ Parser.prototype = {
21048
21029
  return false;
21049
21030
  },
21050
21031
 
21051
- consume: function(e1){
21032
+ consume: function(e1) {
21052
21033
  if (!this.expect(e1)) {
21053
21034
  this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());
21054
21035
  }
@@ -21170,7 +21151,7 @@ Parser.prototype = {
21170
21151
  if ((token = this.expect(':'))) {
21171
21152
  var right = this.assignment();
21172
21153
 
21173
- return extend(function $parseTernary(self, locals){
21154
+ return extend(function $parseTernary(self, locals) {
21174
21155
  return left(self, locals) ? middle(self, locals) : right(self, locals);
21175
21156
  }, {
21176
21157
  constant: left.constant && middle.constant && right.constant
@@ -21330,7 +21311,7 @@ Parser.prototype = {
21330
21311
  },
21331
21312
 
21332
21313
  // This is used with json array declaration
21333
- arrayDeclaration: function () {
21314
+ arrayDeclaration: function() {
21334
21315
  var elementFns = [];
21335
21316
  if (this.peekToken().text !== ']') {
21336
21317
  do {
@@ -21357,7 +21338,7 @@ Parser.prototype = {
21357
21338
  });
21358
21339
  },
21359
21340
 
21360
- object: function () {
21341
+ object: function() {
21361
21342
  var keys = [], valueFns = [];
21362
21343
  if (this.peekToken().text !== '}') {
21363
21344
  do {
@@ -21506,6 +21487,12 @@ function getterFn(path, options, fullExp) {
21506
21487
  return fn;
21507
21488
  }
21508
21489
 
21490
+ var objectValueOf = Object.prototype.valueOf;
21491
+
21492
+ function getValueOf(value) {
21493
+ return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);
21494
+ }
21495
+
21509
21496
  ///////////////////////////////////
21510
21497
 
21511
21498
  /**
@@ -21652,7 +21639,7 @@ function $ParseProvider() {
21652
21639
  // attempt to convert the value to a primitive type
21653
21640
  // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
21654
21641
  // be cheaply dirty-checked
21655
- newValue = newValue.valueOf();
21642
+ newValue = getValueOf(newValue);
21656
21643
 
21657
21644
  if (typeof newValue === 'object') {
21658
21645
  // objects/arrays are not supported - deep-watching them would be too expensive
@@ -21679,7 +21666,7 @@ function $ParseProvider() {
21679
21666
  var newInputValue = inputExpressions(scope);
21680
21667
  if (!expressionInputDirtyCheck(newInputValue, oldInputValue)) {
21681
21668
  lastResult = parsedExpression(scope);
21682
- oldInputValue = newInputValue && newInputValue.valueOf();
21669
+ oldInputValue = newInputValue && getValueOf(newInputValue);
21683
21670
  }
21684
21671
  return lastResult;
21685
21672
  }, listener, objectEquality);
@@ -21696,7 +21683,7 @@ function $ParseProvider() {
21696
21683
  for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
21697
21684
  var newInputValue = inputExpressions[i](scope);
21698
21685
  if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {
21699
- oldInputValueOfValues[i] = newInputValue && newInputValue.valueOf();
21686
+ oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);
21700
21687
  }
21701
21688
  }
21702
21689
 
@@ -21718,7 +21705,7 @@ function $ParseProvider() {
21718
21705
  listener.apply(this, arguments);
21719
21706
  }
21720
21707
  if (isDefined(value)) {
21721
- scope.$$postDigest(function () {
21708
+ scope.$$postDigest(function() {
21722
21709
  if (isDefined(lastValue)) {
21723
21710
  unwatch();
21724
21711
  }
@@ -21737,15 +21724,15 @@ function $ParseProvider() {
21737
21724
  listener.call(this, value, old, scope);
21738
21725
  }
21739
21726
  if (isAllDefined(value)) {
21740
- scope.$$postDigest(function () {
21741
- if(isAllDefined(lastValue)) unwatch();
21727
+ scope.$$postDigest(function() {
21728
+ if (isAllDefined(lastValue)) unwatch();
21742
21729
  });
21743
21730
  }
21744
21731
  }, objectEquality);
21745
21732
 
21746
21733
  function isAllDefined(value) {
21747
21734
  var allDefined = true;
21748
- forEach(value, function (val) {
21735
+ forEach(value, function(val) {
21749
21736
  if (!isDefined(val)) allDefined = false;
21750
21737
  });
21751
21738
  return allDefined;
@@ -22109,7 +22096,7 @@ function qFactory(nextTick, exceptionHandler) {
22109
22096
  } else {
22110
22097
  promise.reject(state.value);
22111
22098
  }
22112
- } catch(e) {
22099
+ } catch (e) {
22113
22100
  promise.reject(e);
22114
22101
  exceptionHandler(e);
22115
22102
  }
@@ -22159,7 +22146,7 @@ function qFactory(nextTick, exceptionHandler) {
22159
22146
  this.promise.$$state.status = 1;
22160
22147
  scheduleProcessQueue(this.promise.$$state);
22161
22148
  }
22162
- } catch(e) {
22149
+ } catch (e) {
22163
22150
  fns[1](e);
22164
22151
  exceptionHandler(e);
22165
22152
  }
@@ -22187,7 +22174,7 @@ function qFactory(nextTick, exceptionHandler) {
22187
22174
  callback = callbacks[i][3];
22188
22175
  try {
22189
22176
  result.notify(isFunction(callback) ? callback(progress) : progress);
22190
- } catch(e) {
22177
+ } catch (e) {
22191
22178
  exceptionHandler(e);
22192
22179
  }
22193
22180
  }
@@ -22252,7 +22239,7 @@ function qFactory(nextTick, exceptionHandler) {
22252
22239
  var callbackOutput = null;
22253
22240
  try {
22254
22241
  if (isFunction(callback)) callbackOutput = callback();
22255
- } catch(e) {
22242
+ } catch (e) {
22256
22243
  return makePromise(e, false);
22257
22244
  }
22258
22245
  if (isPromiseLike(callbackOutput)) {
@@ -22360,7 +22347,7 @@ function qFactory(nextTick, exceptionHandler) {
22360
22347
  return $Q;
22361
22348
  }
22362
22349
 
22363
- function $$RAFProvider(){ //rAF
22350
+ function $$RAFProvider() { //rAF
22364
22351
  this.$get = ['$window', '$timeout', function($window, $timeout) {
22365
22352
  var requestAnimationFrame = $window.requestAnimationFrame ||
22366
22353
  $window.webkitRequestAnimationFrame ||
@@ -22459,7 +22446,7 @@ function $$RAFProvider(){ //rAF
22459
22446
  * They also provide an event emission/broadcast and subscription facility. See the
22460
22447
  * {@link guide/scope developer guide on scopes}.
22461
22448
  */
22462
- function $RootScopeProvider(){
22449
+ function $RootScopeProvider() {
22463
22450
  var TTL = 10;
22464
22451
  var $rootScopeMinErr = minErr('$rootScope');
22465
22452
  var lastDirtyWatch = null;
@@ -22473,7 +22460,7 @@ function $RootScopeProvider(){
22473
22460
  };
22474
22461
 
22475
22462
  this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
22476
- function( $injector, $exceptionHandler, $parse, $browser) {
22463
+ function($injector, $exceptionHandler, $parse, $browser) {
22477
22464
 
22478
22465
  /**
22479
22466
  * @ngdoc type
@@ -22816,7 +22803,7 @@ function $RootScopeProvider(){
22816
22803
  if (!watchExpressions.length) {
22817
22804
  // No expressions means we call the listener ASAP
22818
22805
  var shouldCall = true;
22819
- self.$evalAsync(function () {
22806
+ self.$evalAsync(function() {
22820
22807
  if (shouldCall) listener(newValues, newValues, self);
22821
22808
  });
22822
22809
  return function deregisterWatchGroup() {
@@ -22833,7 +22820,7 @@ function $RootScopeProvider(){
22833
22820
  });
22834
22821
  }
22835
22822
 
22836
- forEach(watchExpressions, function (expr, i) {
22823
+ forEach(watchExpressions, function(expr, i) {
22837
22824
  var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {
22838
22825
  newValues[i] = value;
22839
22826
  oldValues[i] = oldValue;
@@ -23005,7 +22992,7 @@ function $RootScopeProvider(){
23005
22992
  if (oldLength > newLength) {
23006
22993
  // we used to have more keys, need to find them and destroy them.
23007
22994
  changeDetected++;
23008
- for(key in oldValue) {
22995
+ for (key in oldValue) {
23009
22996
  if (!newValue.hasOwnProperty(key)) {
23010
22997
  oldLength--;
23011
22998
  delete oldValue[key];
@@ -23125,7 +23112,7 @@ function $RootScopeProvider(){
23125
23112
  dirty = false;
23126
23113
  current = target;
23127
23114
 
23128
- while(asyncQueue.length) {
23115
+ while (asyncQueue.length) {
23129
23116
  try {
23130
23117
  asyncTask = asyncQueue.shift();
23131
23118
  asyncTask.scope.$eval(asyncTask.expression);
@@ -23182,7 +23169,7 @@ function $RootScopeProvider(){
23182
23169
  // this piece should be kept in sync with the traversal in $broadcast
23183
23170
  if (!(next = (current.$$childHead ||
23184
23171
  (current !== target && current.$$nextSibling)))) {
23185
- while(current !== target && !(next = current.$$nextSibling)) {
23172
+ while (current !== target && !(next = current.$$nextSibling)) {
23186
23173
  current = current.$parent;
23187
23174
  }
23188
23175
  }
@@ -23190,7 +23177,7 @@ function $RootScopeProvider(){
23190
23177
 
23191
23178
  // `break traverseScopesLoop;` takes us to here
23192
23179
 
23193
- if((dirty || asyncQueue.length) && !(ttl--)) {
23180
+ if ((dirty || asyncQueue.length) && !(ttl--)) {
23194
23181
  clearPhase();
23195
23182
  throw $rootScopeMinErr('infdig',
23196
23183
  '{0} $digest() iterations reached. Aborting!\n' +
@@ -23202,7 +23189,7 @@ function $RootScopeProvider(){
23202
23189
 
23203
23190
  clearPhase();
23204
23191
 
23205
- while(postDigestQueue.length) {
23192
+ while (postDigestQueue.length) {
23206
23193
  try {
23207
23194
  postDigestQueue.shift()();
23208
23195
  } catch (e) {
@@ -23358,7 +23345,7 @@ function $RootScopeProvider(){
23358
23345
  asyncQueue.push({scope: this, expression: expr});
23359
23346
  },
23360
23347
 
23361
- $$postDigest : function(fn) {
23348
+ $$postDigest: function(fn) {
23362
23349
  postDigestQueue.push(fn);
23363
23350
  },
23364
23351
 
@@ -23495,8 +23482,11 @@ function $RootScopeProvider(){
23495
23482
 
23496
23483
  var self = this;
23497
23484
  return function() {
23498
- namedListeners[namedListeners.indexOf(listener)] = null;
23499
- decrementListenerCount(self, 1, name);
23485
+ var indexOfListener = namedListeners.indexOf(listener);
23486
+ if (indexOfListener !== -1) {
23487
+ namedListeners[indexOfListener] = null;
23488
+ decrementListenerCount(self, 1, name);
23489
+ }
23500
23490
  };
23501
23491
  },
23502
23492
 
@@ -23628,7 +23618,7 @@ function $RootScopeProvider(){
23628
23618
 
23629
23619
  try {
23630
23620
  listeners[i].apply(null, listenerArgs);
23631
- } catch(e) {
23621
+ } catch (e) {
23632
23622
  $exceptionHandler(e);
23633
23623
  }
23634
23624
  }
@@ -23639,7 +23629,7 @@ function $RootScopeProvider(){
23639
23629
  // (though it differs due to having the extra check for $$listenerCount)
23640
23630
  if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||
23641
23631
  (current !== target && current.$$nextSibling)))) {
23642
- while(current !== target && !(next = current.$$nextSibling)) {
23632
+ while (current !== target && !(next = current.$$nextSibling)) {
23643
23633
  current = current.$parent;
23644
23634
  }
23645
23635
  }
@@ -23693,7 +23683,7 @@ function $RootScopeProvider(){
23693
23683
  while (applyAsyncQueue.length) {
23694
23684
  try {
23695
23685
  applyAsyncQueue.shift()();
23696
- } catch(e) {
23686
+ } catch (e) {
23697
23687
  $exceptionHandler(e);
23698
23688
  }
23699
23689
  }
@@ -23794,15 +23784,6 @@ var SCE_CONTEXTS = {
23794
23784
 
23795
23785
  // Helper functions follow.
23796
23786
 
23797
- // Copied from:
23798
- // http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962
23799
- // Prereq: s is a string.
23800
- function escapeForRegexp(s) {
23801
- return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
23802
- replace(/\x08/g, '\\x08');
23803
- }
23804
-
23805
-
23806
23787
  function adjustMatcher(matcher) {
23807
23788
  if (matcher === 'self') {
23808
23789
  return matcher;
@@ -23938,7 +23919,7 @@ function $SceDelegateProvider() {
23938
23919
  * @description
23939
23920
  * Sets/Gets the whitelist of trusted resource URLs.
23940
23921
  */
23941
- this.resourceUrlWhitelist = function (value) {
23922
+ this.resourceUrlWhitelist = function(value) {
23942
23923
  if (arguments.length) {
23943
23924
  resourceUrlWhitelist = adjustMatchers(value);
23944
23925
  }
@@ -23972,7 +23953,7 @@ function $SceDelegateProvider() {
23972
23953
  * Sets/Gets the blacklist of trusted resource URLs.
23973
23954
  */
23974
23955
 
23975
- this.resourceUrlBlacklist = function (value) {
23956
+ this.resourceUrlBlacklist = function(value) {
23976
23957
  if (arguments.length) {
23977
23958
  resourceUrlBlacklist = adjustMatchers(value);
23978
23959
  }
@@ -24453,7 +24434,7 @@ function $SceProvider() {
24453
24434
  * @description
24454
24435
  * Enables/disables SCE and returns the current value.
24455
24436
  */
24456
- this.enabled = function (value) {
24437
+ this.enabled = function(value) {
24457
24438
  if (arguments.length) {
24458
24439
  enabled = !!value;
24459
24440
  }
@@ -24507,11 +24488,11 @@ function $SceProvider() {
24507
24488
  * sce.js and sceSpecs.js would need to be aware of this detail.
24508
24489
  */
24509
24490
 
24510
- this.$get = ['$document', '$parse', '$sceDelegate', function(
24511
- $document, $parse, $sceDelegate) {
24491
+ this.$get = ['$parse', '$sceDelegate', function(
24492
+ $parse, $sceDelegate) {
24512
24493
  // Prereq: Ensure that we're not running in IE<11 quirks mode. In that mode, IE < 11 allow
24513
24494
  // the "expression(javascript expression)" syntax which is insecure.
24514
- if (enabled && $document[0].documentMode < 8) {
24495
+ if (enabled && msie < 8) {
24515
24496
  throw $sceMinErr('iequirks',
24516
24497
  'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' +
24517
24498
  'mode. You can fix this by adding the text <!doctype html> to the top of your HTML ' +
@@ -24531,7 +24512,7 @@ function $SceProvider() {
24531
24512
  * @description
24532
24513
  * Returns a boolean indicating if SCE is enabled.
24533
24514
  */
24534
- sce.isEnabled = function () {
24515
+ sce.isEnabled = function() {
24535
24516
  return enabled;
24536
24517
  };
24537
24518
  sce.trustAs = $sceDelegate.trustAs;
@@ -24567,7 +24548,7 @@ function $SceProvider() {
24567
24548
  if (parsed.literal && parsed.constant) {
24568
24549
  return parsed;
24569
24550
  } else {
24570
- return $parse(expr, function (value) {
24551
+ return $parse(expr, function(value) {
24571
24552
  return sce.getTrusted(type, value);
24572
24553
  });
24573
24554
  }
@@ -24820,15 +24801,15 @@ function $SceProvider() {
24820
24801
  getTrusted = sce.getTrusted,
24821
24802
  trustAs = sce.trustAs;
24822
24803
 
24823
- forEach(SCE_CONTEXTS, function (enumValue, name) {
24804
+ forEach(SCE_CONTEXTS, function(enumValue, name) {
24824
24805
  var lName = lowercase(name);
24825
- sce[camelCase("parse_as_" + lName)] = function (expr) {
24806
+ sce[camelCase("parse_as_" + lName)] = function(expr) {
24826
24807
  return parse(enumValue, expr);
24827
24808
  };
24828
- sce[camelCase("get_trusted_" + lName)] = function (value) {
24809
+ sce[camelCase("get_trusted_" + lName)] = function(value) {
24829
24810
  return getTrusted(enumValue, value);
24830
24811
  };
24831
- sce[camelCase("trust_as_" + lName)] = function (value) {
24812
+ sce[camelCase("trust_as_" + lName)] = function(value) {
24832
24813
  return trustAs(enumValue, value);
24833
24814
  };
24834
24815
  });
@@ -24859,22 +24840,22 @@ function $SnifferProvider() {
24859
24840
  boxee = /Boxee/i.test(($window.navigator || {}).userAgent),
24860
24841
  document = $document[0] || {},
24861
24842
  vendorPrefix,
24862
- vendorRegex = /^(Moz|webkit|O|ms)(?=[A-Z])/,
24843
+ vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/,
24863
24844
  bodyStyle = document.body && document.body.style,
24864
24845
  transitions = false,
24865
24846
  animations = false,
24866
24847
  match;
24867
24848
 
24868
24849
  if (bodyStyle) {
24869
- for(var prop in bodyStyle) {
24870
- if(match = vendorRegex.exec(prop)) {
24850
+ for (var prop in bodyStyle) {
24851
+ if (match = vendorRegex.exec(prop)) {
24871
24852
  vendorPrefix = match[0];
24872
24853
  vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);
24873
24854
  break;
24874
24855
  }
24875
24856
  }
24876
24857
 
24877
- if(!vendorPrefix) {
24858
+ if (!vendorPrefix) {
24878
24859
  vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';
24879
24860
  }
24880
24861
 
@@ -24915,8 +24896,8 @@ function $SnifferProvider() {
24915
24896
  },
24916
24897
  csp: csp(),
24917
24898
  vendorPrefix: vendorPrefix,
24918
- transitions : transitions,
24919
- animations : animations,
24899
+ transitions: transitions,
24900
+ animations: animations,
24920
24901
  android: android
24921
24902
  };
24922
24903
  }];
@@ -24947,13 +24928,29 @@ function $TemplateRequestProvider() {
24947
24928
  var self = handleRequestFn;
24948
24929
  self.totalPendingRequests++;
24949
24930
 
24950
- return $http.get(tpl, { cache : $templateCache })
24951
- .then(function(response) {
24952
- var html = response.data;
24953
- if(!html || html.length === 0) {
24954
- return handleError();
24931
+ var transformResponse = $http.defaults && $http.defaults.transformResponse;
24932
+
24933
+ if (isArray(transformResponse)) {
24934
+ var original = transformResponse;
24935
+ transformResponse = [];
24936
+ for (var i=0; i<original.length; ++i) {
24937
+ var transformer = original[i];
24938
+ if (transformer !== defaultHttpResponseTransform) {
24939
+ transformResponse.push(transformer);
24955
24940
  }
24941
+ }
24942
+ } else if (transformResponse === defaultHttpResponseTransform) {
24943
+ transformResponse = null;
24944
+ }
24945
+
24946
+ var httpOptions = {
24947
+ cache: $templateCache,
24948
+ transformResponse: transformResponse
24949
+ };
24956
24950
 
24951
+ return $http.get(tpl, httpOptions)
24952
+ .then(function(response) {
24953
+ var html = response.data;
24957
24954
  self.totalPendingRequests--;
24958
24955
  $templateCache.put(tpl, html);
24959
24956
  return html;
@@ -25007,7 +25004,7 @@ function $$TestabilityProvider() {
25007
25004
  if (dataBinding) {
25008
25005
  forEach(dataBinding, function(bindingName) {
25009
25006
  if (opt_exactMatch) {
25010
- var matcher = new RegExp('(^|\\s)' + expression + '(\\s|\\||$)');
25007
+ var matcher = new RegExp('(^|\\s)' + escapeForRegexp(expression) + '(\\s|\\||$)');
25011
25008
  if (matcher.test(bindingName)) {
25012
25009
  matches.push(binding);
25013
25010
  }
@@ -25129,7 +25126,7 @@ function $TimeoutProvider() {
25129
25126
  timeoutId = $browser.defer(function() {
25130
25127
  try {
25131
25128
  deferred.resolve(fn());
25132
- } catch(e) {
25129
+ } catch (e) {
25133
25130
  deferred.reject(e);
25134
25131
  $exceptionHandler(e);
25135
25132
  }
@@ -25295,7 +25292,7 @@ function urlIsSameOrigin(requestUrl) {
25295
25292
  <file name="index.html">
25296
25293
  <script>
25297
25294
  angular.module('windowExample', [])
25298
- .controller('ExampleController', ['$scope', '$window', function ($scope, $window) {
25295
+ .controller('ExampleController', ['$scope', '$window', function($scope, $window) {
25299
25296
  $scope.greeting = 'Hello, World!';
25300
25297
  $scope.doGreeting = function(greeting) {
25301
25298
  $window.alert(greeting);
@@ -25316,7 +25313,7 @@ function urlIsSameOrigin(requestUrl) {
25316
25313
  </file>
25317
25314
  </example>
25318
25315
  */
25319
- function $WindowProvider(){
25316
+ function $WindowProvider() {
25320
25317
  this.$get = valueFn(window);
25321
25318
  }
25322
25319
 
@@ -25425,7 +25422,7 @@ function $FilterProvider($provide) {
25425
25422
  * of the registered filter instances.
25426
25423
  */
25427
25424
  function register(name, factory) {
25428
- if(isObject(name)) {
25425
+ if (isObject(name)) {
25429
25426
  var filters = {};
25430
25427
  forEach(name, function(filter, key) {
25431
25428
  filters[key] = register(key, filter);
@@ -25592,7 +25589,7 @@ function filterFilter() {
25592
25589
 
25593
25590
  predicates.check = function(value, index) {
25594
25591
  for (var j = 0; j < predicates.length; j++) {
25595
- if(!predicates[j](value, index)) {
25592
+ if (!predicates[j](value, index)) {
25596
25593
  return false;
25597
25594
  }
25598
25595
  }
@@ -25621,7 +25618,7 @@ function filterFilter() {
25621
25618
  }
25622
25619
  }
25623
25620
 
25624
- var search = function(obj, text){
25621
+ var search = function(obj, text) {
25625
25622
  if (typeof text === 'string' && text.charAt(0) === '!') {
25626
25623
  return !search(obj, text.substr(1));
25627
25624
  }
@@ -25635,7 +25632,7 @@ function filterFilter() {
25635
25632
  case 'object':
25636
25633
  return comparator(obj, text);
25637
25634
  default:
25638
- for ( var objKey in obj) {
25635
+ for (var objKey in obj) {
25639
25636
  if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
25640
25637
  return true;
25641
25638
  }
@@ -25644,7 +25641,7 @@ function filterFilter() {
25644
25641
  }
25645
25642
  return false;
25646
25643
  case 'array':
25647
- for ( var i = 0; i < obj.length; i++) {
25644
+ for (var i = 0; i < obj.length; i++) {
25648
25645
  if (search(obj[i], text)) {
25649
25646
  return true;
25650
25647
  }
@@ -25679,7 +25676,7 @@ function filterFilter() {
25679
25676
  return array;
25680
25677
  }
25681
25678
  var filtered = [];
25682
- for ( var j = 0; j < array.length; j++) {
25679
+ for (var j = 0; j < array.length; j++) {
25683
25680
  var value = array[j];
25684
25681
  if (predicates.check(value, j)) {
25685
25682
  filtered.push(value);
@@ -25744,7 +25741,7 @@ function filterFilter() {
25744
25741
  currencyFilter.$inject = ['$locale'];
25745
25742
  function currencyFilter($locale) {
25746
25743
  var formats = $locale.NUMBER_FORMATS;
25747
- return function(amount, currencySymbol, fractionSize){
25744
+ return function(amount, currencySymbol, fractionSize) {
25748
25745
  if (isUndefined(currencySymbol)) {
25749
25746
  currencySymbol = formats.CURRENCY_SYM;
25750
25747
  }
@@ -25891,7 +25888,7 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
25891
25888
  }
25892
25889
 
25893
25890
  // format fraction part.
25894
- while(fraction.length < fractionSize) {
25891
+ while (fraction.length < fractionSize) {
25895
25892
  fraction += '0';
25896
25893
  }
25897
25894
 
@@ -25916,7 +25913,7 @@ function padNumber(num, digits, trim) {
25916
25913
  num = -num;
25917
25914
  }
25918
25915
  num = '' + num;
25919
- while(num.length < digits) num = '0' + num;
25916
+ while (num.length < digits) num = '0' + num;
25920
25917
  if (trim)
25921
25918
  num = num.substr(num.length - digits);
25922
25919
  return neg + num;
@@ -25929,7 +25926,7 @@ function dateGetter(name, size, offset, trim) {
25929
25926
  var value = date['get' + name]();
25930
25927
  if (offset > 0 || value > -offset)
25931
25928
  value += offset;
25932
- if (value === 0 && offset == -12 ) value = 12;
25929
+ if (value === 0 && offset == -12) value = 12;
25933
25930
  return padNumber(value, size, trim);
25934
25931
  };
25935
25932
  }
@@ -26154,7 +26151,7 @@ function dateFilter($locale) {
26154
26151
  return date;
26155
26152
  }
26156
26153
 
26157
- while(format) {
26154
+ while (format) {
26158
26155
  match = DATE_FORMATS_SPLIT.exec(format);
26159
26156
  if (match) {
26160
26157
  parts = concat(parts, match, 1);
@@ -26169,7 +26166,7 @@ function dateFilter($locale) {
26169
26166
  date = new Date(date.getTime());
26170
26167
  date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
26171
26168
  }
26172
- forEach(parts, function(value){
26169
+ forEach(parts, function(value) {
26173
26170
  fn = DATE_FORMATS[value];
26174
26171
  text += fn ? fn(date, $locale.DATETIME_FORMATS)
26175
26172
  : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
@@ -26322,7 +26319,7 @@ var uppercaseFilter = valueFn(uppercase);
26322
26319
  </file>
26323
26320
  </example>
26324
26321
  */
26325
- function limitToFilter(){
26322
+ function limitToFilter() {
26326
26323
  return function(input, limit) {
26327
26324
  if (isNumber(input)) input = input.toString();
26328
26325
  if (!isArray(input) && !isString(input)) return input;
@@ -26483,42 +26480,42 @@ function limitToFilter(){
26483
26480
  </example>
26484
26481
  */
26485
26482
  orderByFilter.$inject = ['$parse'];
26486
- function orderByFilter($parse){
26483
+ function orderByFilter($parse) {
26487
26484
  return function(array, sortPredicate, reverseOrder) {
26488
26485
  if (!(isArrayLike(array))) return array;
26489
26486
  sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
26490
26487
  if (sortPredicate.length === 0) { sortPredicate = ['+']; }
26491
- sortPredicate = sortPredicate.map(function(predicate){
26488
+ sortPredicate = sortPredicate.map(function(predicate) {
26492
26489
  var descending = false, get = predicate || identity;
26493
26490
  if (isString(predicate)) {
26494
26491
  if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
26495
26492
  descending = predicate.charAt(0) == '-';
26496
26493
  predicate = predicate.substring(1);
26497
26494
  }
26498
- if ( predicate === '' ) {
26495
+ if (predicate === '') {
26499
26496
  // Effectively no predicate was passed so we compare identity
26500
- return reverseComparator(function(a,b) {
26497
+ return reverseComparator(function(a, b) {
26501
26498
  return compare(a, b);
26502
26499
  }, descending);
26503
26500
  }
26504
26501
  get = $parse(predicate);
26505
26502
  if (get.constant) {
26506
26503
  var key = get();
26507
- return reverseComparator(function(a,b) {
26504
+ return reverseComparator(function(a, b) {
26508
26505
  return compare(a[key], b[key]);
26509
26506
  }, descending);
26510
26507
  }
26511
26508
  }
26512
- return reverseComparator(function(a,b){
26509
+ return reverseComparator(function(a, b) {
26513
26510
  return compare(get(a),get(b));
26514
26511
  }, descending);
26515
26512
  });
26516
26513
  var arrayCopy = [];
26517
- for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }
26514
+ for (var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }
26518
26515
  return arrayCopy.sort(reverseComparator(comparator, reverseOrder));
26519
26516
 
26520
- function comparator(o1, o2){
26521
- for ( var i = 0; i < sortPredicate.length; i++) {
26517
+ function comparator(o1, o2) {
26518
+ for (var i = 0; i < sortPredicate.length; i++) {
26522
26519
  var comp = sortPredicate[i](o1, o2);
26523
26520
  if (comp !== 0) return comp;
26524
26521
  }
@@ -26526,10 +26523,10 @@ function orderByFilter($parse){
26526
26523
  }
26527
26524
  function reverseComparator(comp, descending) {
26528
26525
  return descending
26529
- ? function(a,b){return comp(b,a);}
26526
+ ? function(a, b) {return comp(b,a);}
26530
26527
  : comp;
26531
26528
  }
26532
- function compare(v1, v2){
26529
+ function compare(v1, v2) {
26533
26530
  var t1 = typeof v1;
26534
26531
  var t2 = typeof v2;
26535
26532
  if (t1 == t2) {
@@ -26581,7 +26578,7 @@ var htmlAnchorDirective = valueFn({
26581
26578
  // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
26582
26579
  var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
26583
26580
  'xlink:href' : 'href';
26584
- element.on('click', function(event){
26581
+ element.on('click', function(event) {
26585
26582
  // if we have no href url, then don't navigate anywhere.
26586
26583
  if (!element.attr(href)) {
26587
26584
  event.preventDefault();
@@ -27060,6 +27057,11 @@ function nullFormRenameControl(control, name) {
27060
27057
  * - `pattern`
27061
27058
  * - `required`
27062
27059
  * - `url`
27060
+ * - `date`
27061
+ * - `datetimelocal`
27062
+ * - `time`
27063
+ * - `week`
27064
+ * - `month`
27063
27065
  *
27064
27066
  * @description
27065
27067
  * `FormController` keeps track of all its controls and nested forms as well as the state of them,
@@ -27248,7 +27250,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
27248
27250
  * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
27249
27251
  * saving or resetting it.
27250
27252
  */
27251
- form.$setPristine = function () {
27253
+ form.$setPristine = function() {
27252
27254
  $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);
27253
27255
  form.$dirty = false;
27254
27256
  form.$pristine = true;
@@ -27271,7 +27273,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
27271
27273
  * Setting a form controls back to their untouched state is often useful when setting the form
27272
27274
  * back to its pristine state.
27273
27275
  */
27274
- form.$setUntouched = function () {
27276
+ form.$setUntouched = function() {
27275
27277
  forEach(controls, function(control) {
27276
27278
  control.$setUntouched();
27277
27279
  });
@@ -27284,7 +27286,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
27284
27286
  * @description
27285
27287
  * Sets the form to its submitted state.
27286
27288
  */
27287
- form.$setSubmitted = function () {
27289
+ form.$setSubmitted = function() {
27288
27290
  $animate.addClass(element, SUBMITTED_CLASS);
27289
27291
  form.$submitted = true;
27290
27292
  parentForm.$setSubmitted();
@@ -27561,7 +27563,6 @@ var inputType = {
27561
27563
  * @description
27562
27564
  * Standard HTML text input with angular data binding, inherited by most of the `input` elements.
27563
27565
  *
27564
- * *NOTE* Not every feature offered is available for all input types.
27565
27566
  *
27566
27567
  * @param {string} ngModel Assignable angular expression to data-bind to.
27567
27568
  * @param {string=} name Property name of the form under which the control is published.
@@ -27645,7 +27646,10 @@ var inputType = {
27645
27646
  * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601
27646
27647
  * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many
27647
27648
  * modern browsers do not yet support this input type, it is important to provide cues to users on the
27648
- * expected input format via a placeholder or label. The model must always be a Date object.
27649
+ * expected input format via a placeholder or label.
27650
+ *
27651
+ * The model must always be a Date object, otherwise Angular will throw an error.
27652
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
27649
27653
  *
27650
27654
  * The timezone to be used to read/write the `Date` instance in the model can be defined using
27651
27655
  * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
@@ -27733,7 +27737,10 @@ var inputType = {
27733
27737
  * @description
27734
27738
  * Input with datetime validation and transformation. In browsers that do not yet support
27735
27739
  * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
27736
- * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`. The model must be a Date object.
27740
+ * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`.
27741
+ *
27742
+ * The model must always be a Date object, otherwise Angular will throw an error.
27743
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
27737
27744
  *
27738
27745
  * The timezone to be used to read/write the `Date` instance in the model can be defined using
27739
27746
  * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
@@ -27824,6 +27831,9 @@ var inputType = {
27824
27831
  * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a
27825
27832
  * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.
27826
27833
  *
27834
+ * The model must always be a Date object, otherwise Angular will throw an error.
27835
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
27836
+ *
27827
27837
  * The timezone to be used to read/write the `Date` instance in the model can be defined using
27828
27838
  * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
27829
27839
  *
@@ -27910,7 +27920,10 @@ var inputType = {
27910
27920
  * @description
27911
27921
  * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support
27912
27922
  * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
27913
- * week format (yyyy-W##), for example: `2013-W02`. The model must always be a Date object.
27923
+ * week format (yyyy-W##), for example: `2013-W02`.
27924
+ *
27925
+ * The model must always be a Date object, otherwise Angular will throw an error.
27926
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
27914
27927
  *
27915
27928
  * The timezone to be used to read/write the `Date` instance in the model can be defined using
27916
27929
  * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
@@ -27996,8 +28009,12 @@ var inputType = {
27996
28009
  * @description
27997
28010
  * Input with month validation and transformation. In browsers that do not yet support
27998
28011
  * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
27999
- * month format (yyyy-MM), for example: `2009-01`. The model must always be a Date object. In the event the model is
28000
- * not set to the first of the month, the first of that model's month is assumed.
28012
+ * month format (yyyy-MM), for example: `2009-01`.
28013
+ *
28014
+ * The model must always be a Date object, otherwise Angular will throw an error.
28015
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
28016
+ * If the model is not set to the first of the month, the next view to model update will set it
28017
+ * to the first of the month.
28001
28018
  *
28002
28019
  * The timezone to be used to read/write the `Date` instance in the model can be defined using
28003
28020
  * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
@@ -28086,6 +28103,8 @@ var inputType = {
28086
28103
  * Text input with number validation and transformation. Sets the `number` validation
28087
28104
  * error if not a valid number.
28088
28105
  *
28106
+ * The model must always be a number, otherwise Angular will throw an error.
28107
+ *
28089
28108
  * @param {string} ngModel Assignable angular expression to data-bind to.
28090
28109
  * @param {string=} name Property name of the form under which the control is published.
28091
28110
  * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
@@ -28164,6 +28183,12 @@ var inputType = {
28164
28183
  * Text input with URL validation. Sets the `url` validation error key if the content is not a
28165
28184
  * valid URL.
28166
28185
  *
28186
+ * <div class="alert alert-warning">
28187
+ * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex
28188
+ * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify
28189
+ * the built-in validators (see the {@link guide/forms Forms guide})
28190
+ * </div>
28191
+ *
28167
28192
  * @param {string} ngModel Assignable angular expression to data-bind to.
28168
28193
  * @param {string=} name Property name of the form under which the control is published.
28169
28194
  * @param {string=} required Sets `required` validation error key if the value is not entered.
@@ -28241,6 +28266,12 @@ var inputType = {
28241
28266
  * Text input with email validation. Sets the `email` validation error key if not a valid email
28242
28267
  * address.
28243
28268
  *
28269
+ * <div class="alert alert-warning">
28270
+ * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex
28271
+ * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can
28272
+ * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide})
28273
+ * </div>
28274
+ *
28244
28275
  * @param {string} ngModel Assignable angular expression to data-bind to.
28245
28276
  * @param {string=} name Property name of the form under which the control is published.
28246
28277
  * @param {string=} required Sets `required` validation error key if the value is not entered.
@@ -28419,19 +28450,6 @@ var inputType = {
28419
28450
  'file': noop
28420
28451
  };
28421
28452
 
28422
- function testFlags(validity, flags) {
28423
- var i, flag;
28424
- if (flags) {
28425
- for (i=0; i<flags.length; ++i) {
28426
- flag = flags[i];
28427
- if (validity[flag]) {
28428
- return true;
28429
- }
28430
- }
28431
- }
28432
- return false;
28433
- }
28434
-
28435
28453
  function stringBasedInputType(ctrl) {
28436
28454
  ctrl.$formatters.push(function(value) {
28437
28455
  return ctrl.$isEmpty(value) ? value : value.toString();
@@ -28444,7 +28462,6 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
28444
28462
  }
28445
28463
 
28446
28464
  function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
28447
- var validity = element.prop(VALIDITY_STATE_PROPERTY);
28448
28465
  var placeholder = element[0].placeholder, noevent = {};
28449
28466
  var type = lowercase(element[0].type);
28450
28467
 
@@ -28881,10 +28898,14 @@ function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filt
28881
28898
  * @restrict E
28882
28899
  *
28883
28900
  * @description
28884
- * HTML input element control with angular data-binding. Input control follows HTML5 input types
28885
- * and polyfills the HTML5 validation behavior for older browsers.
28901
+ * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding,
28902
+ * input state control, and validation.
28903
+ * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers.
28886
28904
  *
28887
- * *NOTE* Not every feature offered is available for all input types.
28905
+ * <div class="alert alert-warning">
28906
+ * **Note:** Not every feature offered is available for all input types.
28907
+ * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`.
28908
+ * </div>
28888
28909
  *
28889
28910
  * @param {string} ngModel Assignable angular expression to data-bind to.
28890
28911
  * @param {string=} name Property name of the form under which the control is published.
@@ -29020,19 +29041,20 @@ var VALID_CLASS = 'ng-valid',
29020
29041
  * @name ngModel.NgModelController
29021
29042
  *
29022
29043
  * @property {string} $viewValue Actual string value in the view.
29023
- * @property {*} $modelValue The value in the model, that the control is bound to.
29044
+ * @property {*} $modelValue The value in the model that the control is bound to.
29024
29045
  * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
29025
- the control reads value from the DOM. Each function is called, in turn, passing the value
29026
- through to the next. The last return value is used to populate the model.
29027
- Used to sanitize / convert the value as well as validation. For validation,
29028
- the parsers should update the validity state using
29029
- {@link ngModel.NgModelController#$setValidity $setValidity()},
29030
- and return `undefined` for invalid values.
29046
+ the control reads value from the DOM. The functions are called in array order, each passing the value
29047
+ through to the next. The last return value is forwarded to the $validators collection.
29048
+ Used to sanitize / convert the value.
29049
+ Returning undefined from a parser means a parse error occurred. No $validators will
29050
+ run and the 'ngModel' will not be updated until the parse error is resolved. The parse error is stored
29051
+ in 'ngModel.$error.parse'.
29031
29052
 
29032
29053
  *
29033
29054
  * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever
29034
- the model value changes. Each function is called, in turn, passing the value through to the
29035
- next. Used to format / convert values for display in the control and validation.
29055
+ the model value changes. The functions are called in reverse array order, each passing the value through to the
29056
+ next. The last return value is used as the actual DOM value.
29057
+ Used to format / convert values for display in the control.
29036
29058
  * ```js
29037
29059
  * function formatter(value) {
29038
29060
  * if (value) {
@@ -29063,8 +29085,9 @@ var VALID_CLASS = 'ng-valid',
29063
29085
  * is expected to return a promise when it is run during the model validation process. Once the promise
29064
29086
  * is delivered then the validation status will be set to true when fulfilled and false when rejected.
29065
29087
  * When the asynchronous validators are triggered, each of the validators will run in parallel and the model
29066
- * value will only be updated once all validators have been fulfilled. Also, keep in mind that all
29067
- * asynchronous validators will only run once all synchronous validators have passed.
29088
+ * value will only be updated once all validators have been fulfilled. As long as an asynchronous validator
29089
+ * is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators
29090
+ * will only run once all synchronous validators have passed.
29068
29091
  *
29069
29092
  * Please note that if $http is used then it is important that the server returns a success HTTP response code
29070
29093
  * in order to fulfill the validation and a status level of `4xx` in order to reject the validation.
@@ -29120,7 +29143,7 @@ var VALID_CLASS = 'ng-valid',
29120
29143
  *
29121
29144
  * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}
29122
29145
  * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`).
29123
- * However, as we are using `$sce` the model can still decide to to provide unsafe content if it marks
29146
+ * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks
29124
29147
  * that content using the `$sce` service.
29125
29148
  *
29126
29149
  * <example name="NgModelController" module="customControl" deps="angular-sanitize.js">
@@ -29307,19 +29330,22 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
29307
29330
  * @name ngModel.NgModelController#$setValidity
29308
29331
  *
29309
29332
  * @description
29310
- * Change the validity state, and notifies the form.
29333
+ * Change the validity state, and notify the form.
29311
29334
  *
29312
- * This method can be called within $parsers/$formatters. However, if possible, please use the
29313
- * `ngModel.$validators` pipeline which is designed to call this method automatically.
29335
+ * This method can be called within $parsers/$formatters or a custom validation implementation.
29336
+ * However, in most cases it should be sufficient to use the `ngModel.$validators` and
29337
+ * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically.
29314
29338
  *
29315
- * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign
29316
- * to `$error[validationErrorKey]` and `$pending[validationErrorKey]`
29317
- * so that it is available for data-binding.
29339
+ * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned
29340
+ * to either `$error[validationErrorKey]` or `$pending[validationErrorKey]`
29341
+ * (for unfulfilled `$asyncValidators`), so that it is available for data-binding.
29318
29342
  * The `validationErrorKey` should be in camelCase and will get converted into dash-case
29319
29343
  * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
29320
29344
  * class and can be bound to as `{{someForm.someControl.$error.myError}}` .
29321
29345
  * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined),
29322
- * or skipped (null).
29346
+ * or skipped (null). Pending is used for unfulfilled `$asyncValidators`.
29347
+ * Skipped is used by Angular when validators do not run because of parse errors and
29348
+ * when `$asyncValidators` do not run because any of the `$validators` failed.
29323
29349
  */
29324
29350
  addSetValidityMethod({
29325
29351
  ctrl: this,
@@ -29345,7 +29371,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
29345
29371
  * state (ng-pristine class). A model is considered to be pristine when the model has not been changed
29346
29372
  * from when first compiled within then form.
29347
29373
  */
29348
- this.$setPristine = function () {
29374
+ this.$setPristine = function() {
29349
29375
  ctrl.$dirty = false;
29350
29376
  ctrl.$pristine = true;
29351
29377
  $animate.removeClass($element, DIRTY_CLASS);
@@ -29414,13 +29440,13 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
29414
29440
  * angular.module('cancel-update-example', [])
29415
29441
  *
29416
29442
  * .controller('CancelUpdateController', ['$scope', function($scope) {
29417
- * $scope.resetWithCancel = function (e) {
29443
+ * $scope.resetWithCancel = function(e) {
29418
29444
  * if (e.keyCode == 27) {
29419
29445
  * $scope.myForm.myInput1.$rollbackViewValue();
29420
29446
  * $scope.myValue = '';
29421
29447
  * }
29422
29448
  * };
29423
- * $scope.resetWithoutCancel = function (e) {
29449
+ * $scope.resetWithoutCancel = function(e) {
29424
29450
  * if (e.keyCode == 27) {
29425
29451
  * $scope.myValue = '';
29426
29452
  * }
@@ -29599,7 +29625,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
29599
29625
  var parserValid = isUndefined(modelValue) ? undefined : true;
29600
29626
 
29601
29627
  if (parserValid) {
29602
- for(var i = 0; i < ctrl.$parsers.length; i++) {
29628
+ for (var i = 0; i < ctrl.$parsers.length; i++) {
29603
29629
  modelValue = ctrl.$parsers[i](modelValue);
29604
29630
  if (isUndefined(modelValue)) {
29605
29631
  parserValid = false;
@@ -29640,7 +29666,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
29640
29666
  forEach(ctrl.$viewChangeListeners, function(listener) {
29641
29667
  try {
29642
29668
  listener();
29643
- } catch(e) {
29669
+ } catch (e) {
29644
29670
  $exceptionHandler(e);
29645
29671
  }
29646
29672
  });
@@ -29743,7 +29769,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
29743
29769
  idx = formatters.length;
29744
29770
 
29745
29771
  var viewValue = modelValue;
29746
- while(idx--) {
29772
+ while (idx--) {
29747
29773
  viewValue = formatters[idx](viewValue);
29748
29774
  }
29749
29775
  if (ctrl.$viewValue !== viewValue) {
@@ -29764,6 +29790,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
29764
29790
  * @name ngModel
29765
29791
  *
29766
29792
  * @element input
29793
+ * @priority 1
29767
29794
  *
29768
29795
  * @description
29769
29796
  * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a
@@ -29785,7 +29812,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
29785
29812
  *
29786
29813
  * For best practices on using `ngModel`, see:
29787
29814
  *
29788
- * - [https://github.com/angular/angular.js/wiki/Understanding-Scopes]
29815
+ * - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes)
29789
29816
  *
29790
29817
  * For basic examples, how to use `ngModel`, see:
29791
29818
  *
@@ -29808,10 +29835,15 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
29808
29835
  * The following CSS classes are added and removed on the associated input/select/textarea element
29809
29836
  * depending on the validity of the model.
29810
29837
  *
29811
- * - `ng-valid` is set if the model is valid.
29812
- * - `ng-invalid` is set if the model is invalid.
29813
- * - `ng-pristine` is set if the model is pristine.
29814
- * - `ng-dirty` is set if the model is dirty.
29838
+ * - `ng-valid`: the model is valid
29839
+ * - `ng-invalid`: the model is invalid
29840
+ * - `ng-valid-[key]`: for each valid key added by `$setValidity`
29841
+ * - `ng-invalid-[key]`: for each invalid key added by `$setValidity`
29842
+ * - `ng-pristine`: the control hasn't been interacted with yet
29843
+ * - `ng-dirty`: the control has been interacted with
29844
+ * - `ng-touched`: the control has been blurred
29845
+ * - `ng-untouched`: the control hasn't been blurred
29846
+ * - `ng-pending`: any `$asyncValidators` are unfulfilled
29815
29847
  *
29816
29848
  * Keep in mind that ngAnimate can detect each of these classes when added and removed.
29817
29849
  *
@@ -29905,7 +29937,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
29905
29937
  .controller('ExampleController', ['$scope', function($scope) {
29906
29938
  var _name = 'Brian';
29907
29939
  $scope.user = {
29908
- name: function (newName) {
29940
+ name: function(newName) {
29909
29941
  if (angular.isDefined(newName)) {
29910
29942
  _name = newName;
29911
29943
  }
@@ -30272,9 +30304,9 @@ var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
30272
30304
  * @name ngValue
30273
30305
  *
30274
30306
  * @description
30275
- * Binds the given expression to the value of `input[select]` or `input[radio]`, so
30276
- * that when the element is selected, the `ngModel` of that element is set to the
30277
- * bound value.
30307
+ * Binds the given expression to the value of `option` or `input[radio]`, so
30308
+ * that when the element is selected, the `ngModel` of that element is set to
30309
+ * the bound value.
30278
30310
  *
30279
30311
  * `ngValue` is useful when dynamically generating lists of radio buttons using `ng-repeat`, as
30280
30312
  * shown below.
@@ -30407,7 +30439,7 @@ var ngValueDirective = function() {
30407
30439
  .controller('ExampleController', ['$scope', function($scope) {
30408
30440
  $scope.user = { name: 'say', data: '' };
30409
30441
 
30410
- $scope.cancel = function (e) {
30442
+ $scope.cancel = function(e) {
30411
30443
  if (e.keyCode == 27) {
30412
30444
  $scope.userForm.userName.$rollbackViewValue();
30413
30445
  }
@@ -30481,7 +30513,7 @@ var ngValueDirective = function() {
30481
30513
  .controller('ExampleController', ['$scope', function($scope) {
30482
30514
  var _name = 'Brian';
30483
30515
  $scope.user = {
30484
- name: function (newName) {
30516
+ name: function(newName) {
30485
30517
  return angular.isDefined(newName) ? (_name = newName) : _name;
30486
30518
  }
30487
30519
  };
@@ -30704,7 +30736,7 @@ var ngBindDirective = ['$compile', function($compile) {
30704
30736
  <file name="index.html">
30705
30737
  <script>
30706
30738
  angular.module('bindExample', [])
30707
- .controller('ExampleController', ['$scope', function ($scope) {
30739
+ .controller('ExampleController', ['$scope', function($scope) {
30708
30740
  $scope.salutation = 'Hello';
30709
30741
  $scope.name = 'World';
30710
30742
  }]);
@@ -30859,10 +30891,10 @@ function classDirective(name, selector) {
30859
30891
  attr.$removeClass(newClasses);
30860
30892
  }
30861
30893
 
30862
- function digestClassCounts (classes, count) {
30894
+ function digestClassCounts(classes, count) {
30863
30895
  var classCounts = element.data('$classCounts') || {};
30864
30896
  var classesToUpdate = [];
30865
- forEach(classes, function (className) {
30897
+ forEach(classes, function(className) {
30866
30898
  if (count > 0 || classCounts[className]) {
30867
30899
  classCounts[className] = (classCounts[className] || 0) + count;
30868
30900
  if (classCounts[className] === +(count > 0)) {
@@ -30874,7 +30906,7 @@ function classDirective(name, selector) {
30874
30906
  return classesToUpdate.join(' ');
30875
30907
  }
30876
30908
 
30877
- function updateClasses (oldClasses, newClasses) {
30909
+ function updateClasses(oldClasses, newClasses) {
30878
30910
  var toAdd = arrayDifference(newClasses, oldClasses);
30879
30911
  var toRemove = arrayDifference(oldClasses, newClasses);
30880
30912
  toAdd = digestClassCounts(toAdd, 1);
@@ -30906,23 +30938,23 @@ function classDirective(name, selector) {
30906
30938
  var values = [];
30907
30939
 
30908
30940
  outer:
30909
- for(var i = 0; i < tokens1.length; i++) {
30941
+ for (var i = 0; i < tokens1.length; i++) {
30910
30942
  var token = tokens1[i];
30911
- for(var j = 0; j < tokens2.length; j++) {
30912
- if(token == tokens2[j]) continue outer;
30943
+ for (var j = 0; j < tokens2.length; j++) {
30944
+ if (token == tokens2[j]) continue outer;
30913
30945
  }
30914
30946
  values.push(token);
30915
30947
  }
30916
30948
  return values;
30917
30949
  }
30918
30950
 
30919
- function arrayClasses (classVal) {
30951
+ function arrayClasses(classVal) {
30920
30952
  if (isArray(classVal)) {
30921
30953
  return classVal;
30922
30954
  } else if (isString(classVal)) {
30923
30955
  return classVal.split(' ');
30924
30956
  } else if (isObject(classVal)) {
30925
- var classes = [], i = 0;
30957
+ var classes = [];
30926
30958
  forEach(classVal, function(v, k) {
30927
30959
  if (v) {
30928
30960
  classes = classes.concat(k.split(' '));
@@ -31681,10 +31713,8 @@ var ngControllerDirective = [function() {
31681
31713
  </example>
31682
31714
  */
31683
31715
  /*
31684
- * A directive that allows creation of custom onclick handlers that are defined as angular
31685
- * expressions and are compiled and executed within the current scope.
31686
- *
31687
- * Events that are handled via these handler are always configured not to propagate further.
31716
+ * A collection of directives that allows creation of custom event handlers that are defined as
31717
+ * angular expressions and are compiled and executed within the current scope.
31688
31718
  */
31689
31719
  var ngEventDirectives = {};
31690
31720
 
@@ -32214,13 +32244,13 @@ var ngIfDirective = ['$animate', function($animate) {
32214
32244
  terminal: true,
32215
32245
  restrict: 'A',
32216
32246
  $$tlb: true,
32217
- link: function ($scope, $element, $attr, ctrl, $transclude) {
32247
+ link: function($scope, $element, $attr, ctrl, $transclude) {
32218
32248
  var block, childScope, previousElements;
32219
32249
  $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
32220
32250
 
32221
32251
  if (value) {
32222
32252
  if (!childScope) {
32223
- $transclude(function (clone, newScope) {
32253
+ $transclude(function(clone, newScope) {
32224
32254
  childScope = newScope;
32225
32255
  clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
32226
32256
  // Note: We only need the first/last node of the cloned nodes.
@@ -32452,15 +32482,15 @@ var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce
32452
32482
  currentElement;
32453
32483
 
32454
32484
  var cleanupLastIncludeContent = function() {
32455
- if(previousElement) {
32485
+ if (previousElement) {
32456
32486
  previousElement.remove();
32457
32487
  previousElement = null;
32458
32488
  }
32459
- if(currentScope) {
32489
+ if (currentScope) {
32460
32490
  currentScope.$destroy();
32461
32491
  currentScope = null;
32462
32492
  }
32463
- if(currentElement) {
32493
+ if (currentElement) {
32464
32494
  $animate.leave(currentElement).then(function() {
32465
32495
  previousElement = null;
32466
32496
  });
@@ -33143,10 +33173,10 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
33143
33173
  if (trackByExp) {
33144
33174
  trackByExpGetter = $parse(trackByExp);
33145
33175
  } else {
33146
- trackByIdArrayFn = function (key, value) {
33176
+ trackByIdArrayFn = function(key, value) {
33147
33177
  return hashKey(value);
33148
33178
  };
33149
- trackByIdObjFn = function (key) {
33179
+ trackByIdObjFn = function(key) {
33150
33180
  return key;
33151
33181
  };
33152
33182
  }
@@ -33226,7 +33256,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
33226
33256
  nextBlockOrder[index] = block;
33227
33257
  } else if (nextBlockMap[trackById]) {
33228
33258
  // if collision detected. restore lastBlockMap and throw an error
33229
- forEach(nextBlockOrder, function (block) {
33259
+ forEach(nextBlockOrder, function(block) {
33230
33260
  if (block && block.scope) lastBlockMap[block.id] = block;
33231
33261
  });
33232
33262
  throw ngRepeatMinErr('dupes',
@@ -33416,7 +33446,7 @@ var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
33416
33446
  </div>
33417
33447
  </file>
33418
33448
  <file name="glyphicons.css">
33419
- @import url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css);
33449
+ @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
33420
33450
  </file>
33421
33451
  <file name="animations.css">
33422
33452
  .animate-show {
@@ -33466,13 +33496,13 @@ var ngShowDirective = ['$animate', function($animate) {
33466
33496
  restrict: 'A',
33467
33497
  multiElement: true,
33468
33498
  link: function(scope, element, attr) {
33469
- scope.$watch(attr.ngShow, function ngShowWatchAction(value){
33499
+ scope.$watch(attr.ngShow, function ngShowWatchAction(value) {
33470
33500
  // we're adding a temporary, animation-specific class for ng-hide since this way
33471
33501
  // we can control when the element is actually displayed on screen without having
33472
33502
  // to have a global/greedy CSS selector that breaks when other animations are run.
33473
33503
  // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845
33474
33504
  $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {
33475
- tempClasses : NG_HIDE_IN_PROGRESS_CLASS
33505
+ tempClasses: NG_HIDE_IN_PROGRESS_CLASS
33476
33506
  });
33477
33507
  });
33478
33508
  }
@@ -33581,7 +33611,7 @@ var ngShowDirective = ['$animate', function($animate) {
33581
33611
  </div>
33582
33612
  </file>
33583
33613
  <file name="glyphicons.css">
33584
- @import url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css);
33614
+ @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
33585
33615
  </file>
33586
33616
  <file name="animations.css">
33587
33617
  .animate-hide {
@@ -33627,11 +33657,11 @@ var ngHideDirective = ['$animate', function($animate) {
33627
33657
  restrict: 'A',
33628
33658
  multiElement: true,
33629
33659
  link: function(scope, element, attr) {
33630
- scope.$watch(attr.ngHide, function ngHideWatchAction(value){
33660
+ scope.$watch(attr.ngHide, function ngHideWatchAction(value) {
33631
33661
  // The comment inside of the ngShowDirective explains why we add and
33632
33662
  // remove a temporary class for the show/hide animation
33633
33663
  $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, {
33634
- tempClasses : NG_HIDE_IN_PROGRESS_CLASS
33664
+ tempClasses: NG_HIDE_IN_PROGRESS_CLASS
33635
33665
  });
33636
33666
  });
33637
33667
  }
@@ -34034,34 +34064,37 @@ var ngOptionsMinErr = minErr('ngOptions');
34034
34064
  * elements for the `<select>` element using the array or object obtained by evaluating the
34035
34065
  * `ngOptions` comprehension_expression.
34036
34066
  *
34067
+ * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a
34068
+ * similar result. However, the `ngOptions` provides some benefits such as reducing memory and
34069
+ * increasing speed by not creating a new scope for each repeated instance, as well as providing
34070
+ * more flexibility in how the `select`'s model is assigned via `select as`. `ngOptions should be
34071
+ * used when the `select` model needs to be bound to a non-string value. This is because an option
34072
+ * element can only be bound to string values at present.
34073
+ *
34037
34074
  * When an item in the `<select>` menu is selected, the array element or object property
34038
34075
  * represented by the selected option will be bound to the model identified by the `ngModel`
34039
34076
  * directive.
34040
34077
  *
34041
- * <div class="alert alert-warning">
34042
- * **Note:** `ngModel` compares by reference, not value. This is important when binding to an
34043
- * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).
34044
- * </div>
34045
- *
34046
34078
  * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
34047
34079
  * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
34048
34080
  * option. See example below for demonstration.
34049
34081
  *
34050
34082
  * <div class="alert alert-warning">
34051
- * **Note:** `ngOptions` provides an iterator facility for the `<option>` element which should be used instead
34052
- * of {@link ng.directive:ngRepeat ngRepeat} when you want the
34053
- * `select` model to be bound to a non-string value. This is because an option element can only
34054
- * be bound to string values at present.
34083
+ * **Note:** `ngModel` compares by reference, not value. This is important when binding to an
34084
+ * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).
34055
34085
  * </div>
34056
34086
  *
34057
- * <div class="alert alert-info">
34058
- * **Note:** Using `select as` will bind the result of the `select as` expression to the model, but
34087
+ * ## `select as`
34088
+ *
34089
+ * Using `select as` will bind the result of the `select as` expression to the model, but
34059
34090
  * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)
34060
- * or property name (for object data sources) of the value within the collection.
34061
- * </div>
34091
+ * or property name (for object data sources) of the value within the collection. If a `track by` expression
34092
+ * is used, the result of that expression will be set as the value of the `option` and `select` elements.
34093
+ *
34094
+ * ### `select as` with `trackexpr`
34095
+ *
34096
+ * Using `select as` together with `trackexpr` is not recommended. Reasoning:
34062
34097
  *
34063
- * **Note:** Using `select as` together with `trackexpr` is not recommended.
34064
- * Reasoning:
34065
34098
  * - Example: &lt;select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected"&gt;
34066
34099
  * values: [{id: 1, label: 'aLabel', subItem: {name: 'aSubItem'}}, {id: 2, label: 'bLabel', subItem: {name: 'bSubItem'}}],
34067
34100
  * $scope.selected = {name: 'aSubItem'};
@@ -34272,7 +34305,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
34272
34305
  unknownOption = optionTemplate.clone();
34273
34306
 
34274
34307
  // find "null" option
34275
- for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {
34308
+ for (var i = 0, children = element.children(), ii = children.length; i < ii; i++) {
34276
34309
  if (children[i].value === '') {
34277
34310
  emptyOption = nullOption = children.eq(i);
34278
34311
  break;
@@ -34374,6 +34407,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
34374
34407
  valuesFn = $parse(match[7]),
34375
34408
  track = match[8],
34376
34409
  trackFn = track ? $parse(match[8]) : null,
34410
+ trackKeysCache = {},
34377
34411
  // This is an array of array of existing option groups in DOM.
34378
34412
  // We try to reuse these if possible
34379
34413
  // - optionGroupsCache[0] is the options with no option group
@@ -34419,17 +34453,16 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
34419
34453
 
34420
34454
  function selectionChanged() {
34421
34455
  scope.$apply(function() {
34422
- var optionGroup,
34423
- collection = valuesFn(scope) || [],
34424
- key, value, optionElement, index, groupIndex, length, groupLength, trackIndex;
34456
+ var collection = valuesFn(scope) || [];
34425
34457
  var viewValue;
34426
34458
  if (multiple) {
34427
34459
  viewValue = [];
34428
34460
  forEach(selectElement.val(), function(selectedKey) {
34461
+ selectedKey = trackFn ? trackKeysCache[selectedKey] : selectedKey;
34429
34462
  viewValue.push(getViewValue(selectedKey, collection[selectedKey]));
34430
34463
  });
34431
34464
  } else {
34432
- var selectedKey = selectElement.val();
34465
+ var selectedKey = trackFn ? trackKeysCache[selectElement.val()] : selectElement.val();
34433
34466
  viewValue = getViewValue(selectedKey, collection[selectedKey]);
34434
34467
  }
34435
34468
  ctrl.$setViewValue(viewValue);
@@ -34551,14 +34584,17 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
34551
34584
  anySelected = false,
34552
34585
  lastElement,
34553
34586
  element,
34554
- label;
34587
+ label,
34588
+ optionId;
34589
+
34590
+ trackKeysCache = {};
34555
34591
 
34556
34592
  // We now build up the list of options we need (we merge later)
34557
34593
  for (index = 0; length = keys.length, index < length; index++) {
34558
34594
  key = index;
34559
34595
  if (keyName) {
34560
34596
  key = keys[index];
34561
- if ( key.charAt(0) === '$' ) continue;
34597
+ if (key.charAt(0) === '$') continue;
34562
34598
  }
34563
34599
  value = values[key];
34564
34600
 
@@ -34575,9 +34611,14 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
34575
34611
 
34576
34612
  // doing displayFn(scope, locals) || '' overwrites zero values
34577
34613
  label = isDefined(label) ? label : '';
34614
+ optionId = trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index);
34615
+ if (trackFn) {
34616
+ trackKeysCache[optionId] = key;
34617
+ }
34618
+
34578
34619
  optionGroup.push({
34579
34620
  // either the index into array or key from object
34580
- id: (keyName ? keys[index] : index),
34621
+ id: optionId,
34581
34622
  label: label,
34582
34623
  selected: selected // determine if we should be selected
34583
34624
  });
@@ -34622,7 +34663,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
34622
34663
  }
34623
34664
 
34624
34665
  lastElement = null; // start at the beginning
34625
- for(index = 0, length = optionGroup.length; index < length; index++) {
34666
+ for (index = 0, length = optionGroup.length; index < length; index++) {
34626
34667
  option = optionGroup[index];
34627
34668
  if ((existingOption = existingOptions[index+1])) {
34628
34669
  // reuse elements
@@ -34680,12 +34721,12 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
34680
34721
  }
34681
34722
  // remove any excessive OPTIONs in a group
34682
34723
  index++; // increment since the existingOptions[0] is parent element not OPTION
34683
- while(existingOptions.length > index) {
34724
+ while (existingOptions.length > index) {
34684
34725
  option = existingOptions.pop();
34685
34726
  updateLabelMap(labelMap, option.label, false);
34686
34727
  option.element.remove();
34687
34728
  }
34688
- forEach(labelMap, function (count, label) {
34729
+ forEach(labelMap, function(count, label) {
34689
34730
  if (count > 0) {
34690
34731
  selectCtrl.addOption(label);
34691
34732
  } else if (count < 0) {
@@ -34694,7 +34735,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
34694
34735
  });
34695
34736
  }
34696
34737
  // remove any excessive OPTGROUPs from select
34697
- while(optionGroupsCache.length > groupIndex) {
34738
+ while (optionGroupsCache.length > groupIndex) {
34698
34739
  optionGroupsCache.pop()[0].element.remove();
34699
34740
  }
34700
34741
  }
@@ -34720,7 +34761,7 @@ var optionDirective = ['$interpolate', function($interpolate) {
34720
34761
  }
34721
34762
  }
34722
34763
 
34723
- return function (scope, element, attr) {
34764
+ return function(scope, element, attr) {
34724
34765
  var selectCtrlName = '$selectController',
34725
34766
  parent = element.parent(),
34726
34767
  selectCtrl = parent.data(selectCtrlName) ||
@@ -34992,7 +35033,7 @@ function callerFile(offset) {
34992
35033
  *
34993
35034
  * To work around this we instead use our own handler that fires a real event.
34994
35035
  */
34995
- (function(fn){
35036
+ (function(fn) {
34996
35037
  // We need a handle to the original trigger function for input tests.
34997
35038
  var parentTrigger = fn._originalTrigger = fn.trigger;
34998
35039
  fn.trigger = function(type) {
@@ -35022,7 +35063,7 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
35022
35063
  bindSelector = '.ng-binding:visible';
35023
35064
  if (angular.isString(bindExp)) {
35024
35065
  bindExp = bindExp.replace(/\s/g, '');
35025
- match = function (actualExp) {
35066
+ match = function(actualExp) {
35026
35067
  if (actualExp) {
35027
35068
  actualExp = actualExp.replace(/\s/g, '');
35028
35069
  if (actualExp == bindExp) return true;
@@ -35058,7 +35099,7 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
35058
35099
  var element = windowJquery(this),
35059
35100
  bindings;
35060
35101
  if (bindings = element.data('$binding')) {
35061
- for(var expressions = [], binding, j=0, jj=bindings.length; j<jj; j++) {
35102
+ for (var expressions = [], binding, j=0, jj=bindings.length; j<jj; j++) {
35062
35103
  binding = bindings[j];
35063
35104
 
35064
35105
  if (binding.expressions) {
@@ -35068,7 +35109,7 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
35068
35109
  }
35069
35110
  for (var scope, expression, i = 0, ii = expressions.length; i < ii; i++) {
35070
35111
  expression = expressions[i];
35071
- if(match(expression)) {
35112
+ if (match(expression)) {
35072
35113
  scope = scope || element.scope();
35073
35114
  push(scope.$eval(expression));
35074
35115
  }
@@ -35080,12 +35121,6 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
35080
35121
  };
35081
35122
 
35082
35123
  (function() {
35083
- /**
35084
- * documentMode is an IE-only property
35085
- * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
35086
- */
35087
- var msie = document.documentMode;
35088
-
35089
35124
  /**
35090
35125
  * Triggers a browser event. Attempts to choose the right event if one is
35091
35126
  * not specified.
@@ -35136,8 +35171,8 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
35136
35171
  }
35137
35172
 
35138
35173
  var evnt;
35139
- if(/transitionend/.test(eventType)) {
35140
- if(window.WebKitTransitionEvent) {
35174
+ if (/transitionend/.test(eventType)) {
35175
+ if (window.WebKitTransitionEvent) {
35141
35176
  evnt = new WebKitTransitionEvent(eventType, eventData);
35142
35177
  evnt.initEvent(eventType, false, true);
35143
35178
  }
@@ -35145,14 +35180,14 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
35145
35180
  try {
35146
35181
  evnt = new TransitionEvent(eventType, eventData);
35147
35182
  }
35148
- catch(e) {
35183
+ catch (e) {
35149
35184
  evnt = document.createEvent('TransitionEvent');
35150
35185
  evnt.initTransitionEvent(eventType, null, null, null, eventData.elapsedTime || 0);
35151
35186
  }
35152
35187
  }
35153
35188
  }
35154
- else if(/animationend/.test(eventType)) {
35155
- if(window.WebKitAnimationEvent) {
35189
+ else if (/animationend/.test(eventType)) {
35190
+ if (window.WebKitAnimationEvent) {
35156
35191
  evnt = new WebKitAnimationEvent(eventType, eventData);
35157
35192
  evnt.initEvent(eventType, false, true);
35158
35193
  }
@@ -35160,7 +35195,7 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
35160
35195
  try {
35161
35196
  evnt = new AnimationEvent(eventType, eventData);
35162
35197
  }
35163
- catch(e) {
35198
+ catch (e) {
35164
35199
  evnt = document.createEvent('AnimationEvent');
35165
35200
  evnt.initAnimationEvent(eventType, null, null, null, eventData.elapsedTime || 0);
35166
35201
  }
@@ -35179,7 +35214,7 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
35179
35214
  * read */
35180
35215
  evnt.$manualTimeStamp = eventData.timeStamp;
35181
35216
 
35182
- if(!evnt) return;
35217
+ if (!evnt) return;
35183
35218
 
35184
35219
  var originalPreventDefault = evnt.preventDefault,
35185
35220
  appWindow = element.ownerDocument.defaultView,
@@ -35316,7 +35351,7 @@ angular.scenario.Application.prototype.executeAction = function(action) {
35316
35351
  return $injector;
35317
35352
  };
35318
35353
 
35319
- $injector.invoke(function($browser){
35354
+ $injector.invoke(function($browser) {
35320
35355
  $browser.notifyWhenNoOutstandingRequests(function() {
35321
35356
  action.call(self, $window, $element);
35322
35357
  });
@@ -35506,7 +35541,7 @@ angular.scenario.Future.prototype.execute = function(doneFn) {
35506
35541
  if (result) {
35507
35542
  try {
35508
35543
  result = self.parser(result);
35509
- } catch(e) {
35544
+ } catch (e) {
35510
35545
  error = e;
35511
35546
  }
35512
35547
  }
@@ -36137,7 +36172,7 @@ angular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior,
36137
36172
  });
36138
36173
  var result = $document.find(selector);
36139
36174
  if (selector.match(NG)) {
36140
- angular.forEach(['[ng-','[data-ng-','[x-ng-'], function(value, index){
36175
+ angular.forEach(['[ng-','[data-ng-','[x-ng-'], function(value, index) {
36141
36176
  result = result.add(selector.replace(NG, value), $document);
36142
36177
  });
36143
36178
  }
@@ -36153,7 +36188,7 @@ angular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior,
36153
36188
 
36154
36189
  try {
36155
36190
  behavior.call(self, $window, $document, done);
36156
- } catch(e) {
36191
+ } catch (e) {
36157
36192
  if (e.type && e.type === 'selector') {
36158
36193
  done(e.message);
36159
36194
  } else {
@@ -36468,7 +36503,7 @@ angular.scenario.dsl('select', function() {
36468
36503
  if (option.length) {
36469
36504
  select.val(value);
36470
36505
  } else {
36471
- option = select.find('option').filter(function(){
36506
+ option = select.find('option').filter(function() {
36472
36507
  return _jQuery(this).text() === value;
36473
36508
  });
36474
36509
  if (!option.length) {