angularjs-rails 1.2.16 → 1.2.18

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 41df1107244cece1c3506bdabe6561f49e5adfd8
4
- data.tar.gz: 46f193e4e925ea06734a74572fc8d60308b2dd1c
3
+ metadata.gz: 675564da011e5c4251d43ebea6633404e83678eb
4
+ data.tar.gz: 953fcb7ebf68a070bbb4774b80f13fc2e46965d2
5
5
  SHA512:
6
- metadata.gz: 31881a2f3e57114bac4aa5b62d41af25ce9ee97aef793632ebf179218f3b5ec811623c7c5e6c3ab1d51e5151da5e131887fc55724e27ae7cbce5963a57583d3e
7
- data.tar.gz: 17e76073f357362183a4f5c42c48b21788ecd60d290c006d6338a78521da2b95867a321003d87ca68a8dd430dff20c6e13315fcff32fec9eadac9f1674679e73
6
+ metadata.gz: 784a867e11120831117cd13ad1e3acd7139898df31b23876ee9252e4c8ff258120c67e48b598e41244307c289006b84765dc4fadb9e943d04ea810edde631762
7
+ data.tar.gz: 9c67f83ad585c191fd331fb1f0a7b1f2c39cbb6db7e8e9ce4367b85eb45653a14fffce211c1f503a4fe7e9e3895f5f713655d2ffab9456bc28a55af88f150c1d
@@ -1,6 +1,6 @@
1
1
  module AngularJS
2
2
  module Rails
3
- VERSION = "1.2.16"
4
- UNSTABLE_VERSION = "1.3.0-beta.5"
3
+ VERSION = "1.2.18"
4
+ UNSTABLE_VERSION = "1.3.0-beta.13"
5
5
  end
6
6
  end
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.2.16
2
+ * @license AngularJS v1.2.18
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -295,6 +295,10 @@ angular.module('ngAnimate', ['ng'])
295
295
  }
296
296
  }
297
297
 
298
+ function prepareElement(element) {
299
+ return element && angular.element(element);
300
+ }
301
+
298
302
  function stripCommentsFromElement(element) {
299
303
  return angular.element(extractElementNode(element));
300
304
  }
@@ -503,7 +507,7 @@ angular.module('ngAnimate', ['ng'])
503
507
  /**
504
508
  * @ngdoc service
505
509
  * @name $animate
506
- * @function
510
+ * @kind function
507
511
  *
508
512
  * @description
509
513
  * The `$animate` service provides animation detection support while performing DOM operations (enter, leave and move) as well as during addClass and removeClass operations.
@@ -523,7 +527,7 @@ angular.module('ngAnimate', ['ng'])
523
527
  /**
524
528
  * @ngdoc method
525
529
  * @name $animate#enter
526
- * @function
530
+ * @kind function
527
531
  *
528
532
  * @description
529
533
  * Appends the element to the parentElement element that resides in the document and then runs the enter animation. Once
@@ -550,6 +554,10 @@ angular.module('ngAnimate', ['ng'])
550
554
  * @param {function()=} doneCallback the callback function that will be called once the animation is complete
551
555
  */
552
556
  enter : function(element, parentElement, afterElement, doneCallback) {
557
+ element = angular.element(element);
558
+ parentElement = prepareElement(parentElement);
559
+ afterElement = prepareElement(afterElement);
560
+
553
561
  this.enabled(false, element);
554
562
  $delegate.enter(element, parentElement, afterElement);
555
563
  $rootScope.$$postDigest(function() {
@@ -561,7 +569,7 @@ angular.module('ngAnimate', ['ng'])
561
569
  /**
562
570
  * @ngdoc method
563
571
  * @name $animate#leave
564
- * @function
572
+ * @kind function
565
573
  *
566
574
  * @description
567
575
  * Runs the leave animation operation and, upon completion, removes the element from the DOM. Once
@@ -586,6 +594,7 @@ angular.module('ngAnimate', ['ng'])
586
594
  * @param {function()=} doneCallback the callback function that will be called once the animation is complete
587
595
  */
588
596
  leave : function(element, doneCallback) {
597
+ element = angular.element(element);
589
598
  cancelChildAnimations(element);
590
599
  this.enabled(false, element);
591
600
  $rootScope.$$postDigest(function() {
@@ -598,7 +607,7 @@ angular.module('ngAnimate', ['ng'])
598
607
  /**
599
608
  * @ngdoc method
600
609
  * @name $animate#move
601
- * @function
610
+ * @kind function
602
611
  *
603
612
  * @description
604
613
  * Fires the move DOM operation. Just before the animation starts, the animate service will either append it into the parentElement container or
@@ -626,6 +635,10 @@ angular.module('ngAnimate', ['ng'])
626
635
  * @param {function()=} doneCallback the callback function that will be called once the animation is complete
627
636
  */
628
637
  move : function(element, parentElement, afterElement, doneCallback) {
638
+ element = angular.element(element);
639
+ parentElement = prepareElement(parentElement);
640
+ afterElement = prepareElement(afterElement);
641
+
629
642
  cancelChildAnimations(element);
630
643
  this.enabled(false, element);
631
644
  $delegate.move(element, parentElement, afterElement);
@@ -665,6 +678,7 @@ angular.module('ngAnimate', ['ng'])
665
678
  * @param {function()=} doneCallback the callback function that will be called once the animation is complete
666
679
  */
667
680
  addClass : function(element, className, doneCallback) {
681
+ element = angular.element(element);
668
682
  element = stripCommentsFromElement(element);
669
683
  performAnimation('addClass', className, element, null, null, function() {
670
684
  $delegate.addClass(element, className);
@@ -701,6 +715,7 @@ angular.module('ngAnimate', ['ng'])
701
715
  * @param {function()=} doneCallback the callback function that will be called once the animation is complete
702
716
  */
703
717
  removeClass : function(element, className, doneCallback) {
718
+ element = angular.element(element);
704
719
  element = stripCommentsFromElement(element);
705
720
  performAnimation('removeClass', className, element, null, null, function() {
706
721
  $delegate.removeClass(element, className);
@@ -714,7 +729,7 @@ angular.module('ngAnimate', ['ng'])
714
729
  * @function
715
730
  * @description Adds and/or removes the given CSS classes to and from the element.
716
731
  * Once complete, the done() callback will be fired (if provided).
717
- * @param {DOMElement} element the element which will it's CSS classes changed
732
+ * @param {DOMElement} element the element which will its CSS classes changed
718
733
  * removed from it
719
734
  * @param {string} add the CSS classes which will be added to the element
720
735
  * @param {string} remove the CSS class which will be removed from the element
@@ -722,6 +737,7 @@ angular.module('ngAnimate', ['ng'])
722
737
  * CSS classes have been set on the element
723
738
  */
724
739
  setClass : function(element, add, remove, doneCallback) {
740
+ element = angular.element(element);
725
741
  element = stripCommentsFromElement(element);
726
742
  performAnimation('setClass', [add, remove], element, null, null, function() {
727
743
  $delegate.setClass(element, add, remove);
@@ -731,7 +747,7 @@ angular.module('ngAnimate', ['ng'])
731
747
  /**
732
748
  * @ngdoc method
733
749
  * @name $animate#enabled
734
- * @function
750
+ * @kind function
735
751
  *
736
752
  * @param {boolean=} value If provided then set the animation on or off.
737
753
  * @param {DOMElement=} element If provided then the element will be used to represent the enable/disable operation
@@ -855,6 +871,7 @@ angular.module('ngAnimate', ['ng'])
855
871
  }
856
872
 
857
873
  if(skipAnimation) {
874
+ fireDOMOperation();
858
875
  fireBeforeCallbackAsync();
859
876
  fireAfterCallbackAsync();
860
877
  fireDoneCallbackAsync();
@@ -1373,7 +1390,7 @@ angular.module('ngAnimate', ['ng'])
1373
1390
  //the jqLite object, so we're safe to use a single variable to house
1374
1391
  //the styles since there is always only one element being animated
1375
1392
  var oldStyle = node.getAttribute('style') || '';
1376
- node.setAttribute('style', oldStyle + ' ' + style);
1393
+ node.setAttribute('style', oldStyle + '; ' + style);
1377
1394
  }
1378
1395
 
1379
1396
  element.on(css3AnimationEvents, onAnimationProgress);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.2.16
2
+ * @license AngularJS v1.2.18
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -37,18 +37,15 @@ angular.module('ngCookies', ['ng']).
37
37
  * Requires the {@link ngCookies `ngCookies`} module to be installed.
38
38
  *
39
39
  * @example
40
- <example>
41
- <file name="index.html">
42
- <script>
43
- function ExampleController($cookies) {
44
- // Retrieving a cookie
45
- var favoriteCookie = $cookies.myFavorite;
46
- // Setting a cookie
47
- $cookies.myFavorite = 'oatmeal';
48
- }
49
- </script>
50
- </file>
51
- </example>
40
+ *
41
+ * ```js
42
+ * function ExampleController($cookies) {
43
+ * // Retrieving a cookie
44
+ * var favoriteCookie = $cookies.myFavorite;
45
+ * // Setting a cookie
46
+ * $cookies.myFavorite = 'oatmeal';
47
+ * }
48
+ * ```
52
49
  */
53
50
  factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {
54
51
  var cookies = {},
@@ -143,6 +140,17 @@ angular.module('ngCookies', ['ng']).
143
140
  * Requires the {@link ngCookies `ngCookies`} module to be installed.
144
141
  *
145
142
  * @example
143
+ *
144
+ * ```js
145
+ * function ExampleController($cookies) {
146
+ * // Put cookie
147
+ * $cookieStore.put('myFavorite','oatmeal');
148
+ * // Get cookie
149
+ * var favoriteCookie = $cookieStore.get('myFavorite');
150
+ * // Removing a cookie
151
+ * $cookieStore.remove('myFavorite');
152
+ * }
153
+ * ```
146
154
  */
147
155
  factory('$cookieStore', ['$cookies', function($cookies) {
148
156
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.2.16
2
+ * @license AngularJS v1.2.18
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -69,7 +69,7 @@ function minErr(module) {
69
69
  return match;
70
70
  });
71
71
 
72
- message = message + '\nhttp://errors.angularjs.org/1.2.16/' +
72
+ message = message + '\nhttp://errors.angularjs.org/1.2.18/' +
73
73
  (module ? module + '/' : '') + code;
74
74
  for (i = 2; i < arguments.length; i++) {
75
75
  message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
@@ -124,7 +124,7 @@ function setupModuleLoader(window) {
124
124
  *
125
125
  * # Module
126
126
  *
127
- * A module is a collection of services, directives, filters, and configuration information.
127
+ * A module is a collection of services, directives, controllers, filters, and configuration information.
128
128
  * `angular.module` is used to configure the {@link auto.$injector $injector}.
129
129
  *
130
130
  * ```js
@@ -152,9 +152,9 @@ function setupModuleLoader(window) {
152
152
  * {@link angular.bootstrap} to simplify this process for you.
153
153
  *
154
154
  * @param {!string} name The name of the module to create or retrieve.
155
- <<<<<* @param {!Array.<string>=} requires If specified then new module is being created. If
156
- >>>>>* unspecified then the module is being retrieved for further configuration.
157
- * @param {Function} configFn Optional configuration function for the module. Same as
155
+ * @param {!Array.<string>=} requires If specified then new module is being created. If
156
+ * unspecified then the module is being retrieved for further configuration.
157
+ * @param {Function=} configFn Optional configuration function for the module. Same as
158
158
  * {@link angular.Module#config Module#config()}.
159
159
  * @returns {module} new module with the {@link angular.Module} api.
160
160
  */
@@ -346,6 +346,8 @@ function setupModuleLoader(window) {
346
346
  * configuration.
347
347
  * @description
348
348
  * Use this method to register work which needs to be performed on module loading.
349
+ * For more about how to configure services, see
350
+ * {@link providers#providers_provider-recipe Provider Recipe}.
349
351
  */
350
352
  config: config,
351
353
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.2.16
2
+ * @license AngularJS v1.2.18
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -900,7 +900,7 @@ angular.mock.dump = function(object) {
900
900
  * When an Angular application needs some data from a server, it calls the $http service, which
901
901
  * sends the request to a real server using $httpBackend service. With dependency injection, it is
902
902
  * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify
903
- * the requests and respond with some testing data without sending a request to real server.
903
+ * the requests and respond with some testing data without sending a request to a real server.
904
904
  *
905
905
  * There are two ways to specify what test data should be returned as http responses by the mock
906
906
  * backend when the code under test makes http requests:
@@ -1800,7 +1800,9 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
1800
1800
  *
1801
1801
  * // adds a new phone to the phones array
1802
1802
  * $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
1803
- * phones.push(angular.fromJson(data));
1803
+ * var phone = angular.fromJson(data);
1804
+ * phones.push(phone);
1805
+ * return [200, phone, {}];
1804
1806
  * });
1805
1807
  * $httpBackend.whenGET(/^\/templates\//).passThrough();
1806
1808
  * //...
@@ -1956,11 +1958,11 @@ if(window.jasmine || window.mocha) {
1956
1958
  };
1957
1959
 
1958
1960
 
1959
- beforeEach(function() {
1961
+ (window.beforeEach || window.setup)(function() {
1960
1962
  currentSpec = this;
1961
1963
  });
1962
1964
 
1963
- afterEach(function() {
1965
+ (window.afterEach || window.teardown)(function() {
1964
1966
  var injector = currentSpec.$injector;
1965
1967
 
1966
1968
  currentSpec.$injector = null;
@@ -2002,7 +2004,7 @@ if(window.jasmine || window.mocha) {
2002
2004
  * @param {...(string|Function|Object)} fns any number of modules which are represented as string
2003
2005
  * aliases or as anonymous module initialization functions. The modules are used to
2004
2006
  * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an
2005
- * object literal is passed they will be register as values in the module, the key being
2007
+ * object literal is passed they will be registered as values in the module, the key being
2006
2008
  * the module name and the value being what is returned.
2007
2009
  */
2008
2010
  window.module = angular.mock.module = function() {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.2.16
2
+ * @license AngularJS v1.2.18
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -99,8 +99,8 @@ function shallowClearAndCopy(src, dst) {
99
99
  * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in
100
100
  * URL `/path/greet?salutation=Hello`.
101
101
  *
102
- * If the parameter value is prefixed with `@` then the value of that parameter is extracted from
103
- * the data object (useful for non-GET operations).
102
+ * If the parameter value is prefixed with `@` then the value of that parameter will be taken
103
+ * from the corresponding key on the data object (useful for non-GET operations).
104
104
  *
105
105
  * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend
106
106
  * the default set of resource actions. The declaration should be created in the format of {@link
@@ -527,23 +527,32 @@ angular.module('ngResource', ['ng']).
527
527
  extend({}, extractParams(data, action.params || {}), params),
528
528
  action.url);
529
529
 
530
- var promise = $http(httpConfig).then(function(response) {
530
+ var promise = $http(httpConfig).then(function (response) {
531
531
  var data = response.data,
532
- promise = value.$promise;
532
+ promise = value.$promise;
533
533
 
534
534
  if (data) {
535
535
  // Need to convert action.isArray to boolean in case it is undefined
536
536
  // jshint -W018
537
537
  if (angular.isArray(data) !== (!!action.isArray)) {
538
- throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected ' +
539
- 'response to contain an {0} but got an {1}',
540
- action.isArray?'array':'object', angular.isArray(data)?'array':'object');
538
+ throw $resourceMinErr('badcfg',
539
+ 'Error in resource configuration. Expected ' +
540
+ 'response to contain an {0} but got an {1}',
541
+ action.isArray ? 'array' : 'object',
542
+ angular.isArray(data) ? 'array' : 'object');
541
543
  }
542
544
  // jshint +W018
543
545
  if (action.isArray) {
544
546
  value.length = 0;
545
- forEach(data, function(item) {
546
- value.push(new Resource(item));
547
+ forEach(data, function (item) {
548
+ if (typeof item === "object") {
549
+ value.push(new Resource(item));
550
+ } else {
551
+ // Valid JSON values may be string literals, and these should not be converted
552
+ // into objects. These items will not have access to the Resource prototype
553
+ // methods, but unfortunately there
554
+ value.push(item);
555
+ }
547
556
  });
548
557
  } else {
549
558
  shallowClearAndCopy(data, value);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.2.16
2
+ * @license AngularJS v1.2.18
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -27,7 +27,7 @@ var ngRouteModule = angular.module('ngRoute', ['ng']).
27
27
  /**
28
28
  * @ngdoc provider
29
29
  * @name $routeProvider
30
- * @function
30
+ * @kind function
31
31
  *
32
32
  * @description
33
33
  *
@@ -632,7 +632,7 @@ ngRouteModule.provider('$routeParams', $RouteParamsProvider);
632
632
  * // Route: /Chapter/:chapterId/Section/:sectionId
633
633
  * //
634
634
  * // Then
635
- * $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}
635
+ * $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}
636
636
  * ```
637
637
  */
638
638
  function $RouteParamsProvider() {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.2.16
2
+ * @license AngularJS v1.2.18
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -42,7 +42,7 @@ var $sanitizeMinErr = angular.$$minErr('$sanitize');
42
42
  /**
43
43
  * @ngdoc service
44
44
  * @name $sanitize
45
- * @function
45
+ * @kind function
46
46
  *
47
47
  * @description
48
48
  * The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are
@@ -166,6 +166,7 @@ var START_TAG_REGEXP =
166
166
  COMMENT_REGEXP = /<!--(.*?)-->/g,
167
167
  DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,
168
168
  CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
169
+ SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
169
170
  // Match everything outside of normal chars and " (quote character)
170
171
  NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;
171
172
 
@@ -404,6 +405,11 @@ function decodeEntities(value) {
404
405
  function encodeEntities(value) {
405
406
  return value.
406
407
  replace(/&/g, '&amp;').
408
+ replace(SURROGATE_PAIR_REGEXP, function (value) {
409
+ var hi = value.charCodeAt(0);
410
+ var low = value.charCodeAt(1);
411
+ return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
412
+ }).
407
413
  replace(NON_ALPHANUMERIC_REGEXP, function(value){
408
414
  return '&#' + value.charCodeAt(0) + ';';
409
415
  }).
@@ -476,7 +482,7 @@ angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
476
482
  /**
477
483
  * @ngdoc filter
478
484
  * @name linky
479
- * @function
485
+ * @kind function
480
486
  *
481
487
  * @description
482
488
  * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
@@ -9790,7 +9790,7 @@ if ( typeof module === "object" && module && typeof module.exports === "object"
9790
9790
  })( window );
9791
9791
 
9792
9792
  /**
9793
- * @license AngularJS v1.2.16
9793
+ * @license AngularJS v1.2.18
9794
9794
  * (c) 2010-2014 Google, Inc. http://angularjs.org
9795
9795
  * License: MIT
9796
9796
  */
@@ -9860,7 +9860,7 @@ function minErr(module) {
9860
9860
  return match;
9861
9861
  });
9862
9862
 
9863
- message = message + '\nhttp://errors.angularjs.org/1.2.16/' +
9863
+ message = message + '\nhttp://errors.angularjs.org/1.2.18/' +
9864
9864
  (module ? module + '/' : '') + code;
9865
9865
  for (i = 2; i < arguments.length; i++) {
9866
9866
  message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
@@ -9881,7 +9881,6 @@ function minErr(module) {
9881
9881
  -push,
9882
9882
  -toString,
9883
9883
  -ngMinErr,
9884
- -_angular,
9885
9884
  -angularModule,
9886
9885
  -nodeName_,
9887
9886
  -uid,
@@ -9978,7 +9977,7 @@ function minErr(module) {
9978
9977
  * @ngdoc function
9979
9978
  * @name angular.lowercase
9980
9979
  * @module ng
9981
- * @function
9980
+ * @kind function
9982
9981
  *
9983
9982
  * @description Converts the specified string to lowercase.
9984
9983
  * @param {string} string String to be converted to lowercase.
@@ -9991,7 +9990,7 @@ var hasOwnProperty = Object.prototype.hasOwnProperty;
9991
9990
  * @ngdoc function
9992
9991
  * @name angular.uppercase
9993
9992
  * @module ng
9994
- * @function
9993
+ * @kind function
9995
9994
  *
9996
9995
  * @description Converts the specified string to uppercase.
9997
9996
  * @param {string} string String to be converted to uppercase.
@@ -10032,8 +10031,6 @@ var /** holds major version number for IE or NaN for real browsers */
10032
10031
  toString = Object.prototype.toString,
10033
10032
  ngMinErr = minErr('ng'),
10034
10033
 
10035
-
10036
- _angular = window.angular,
10037
10034
  /** @name angular */
10038
10035
  angular = window.angular || (window.angular = {}),
10039
10036
  angularModule,
@@ -10075,7 +10072,7 @@ function isArrayLike(obj) {
10075
10072
  * @ngdoc function
10076
10073
  * @name angular.forEach
10077
10074
  * @module ng
10078
- * @function
10075
+ * @kind function
10079
10076
  *
10080
10077
  * @description
10081
10078
  * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
@@ -10089,7 +10086,7 @@ function isArrayLike(obj) {
10089
10086
  ```js
10090
10087
  var values = {name: 'misko', gender: 'male'};
10091
10088
  var log = [];
10092
- angular.forEach(values, function(value, key){
10089
+ angular.forEach(values, function(value, key) {
10093
10090
  this.push(key + ': ' + value);
10094
10091
  }, log);
10095
10092
  expect(log).toEqual(['name: misko', 'gender: male']);
@@ -10103,7 +10100,7 @@ function isArrayLike(obj) {
10103
10100
  function forEach(obj, iterator, context) {
10104
10101
  var key;
10105
10102
  if (obj) {
10106
- if (isFunction(obj)){
10103
+ if (isFunction(obj)) {
10107
10104
  for (key in obj) {
10108
10105
  // Need to check if hasOwnProperty exists,
10109
10106
  // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
@@ -10204,7 +10201,7 @@ function setHashKey(obj, h) {
10204
10201
  * @ngdoc function
10205
10202
  * @name angular.extend
10206
10203
  * @module ng
10207
- * @function
10204
+ * @kind function
10208
10205
  *
10209
10206
  * @description
10210
10207
  * Extends the destination object `dst` by copying all of the properties from the `src` object(s)
@@ -10216,9 +10213,9 @@ function setHashKey(obj, h) {
10216
10213
  */
10217
10214
  function extend(dst) {
10218
10215
  var h = dst.$$hashKey;
10219
- forEach(arguments, function(obj){
10216
+ forEach(arguments, function(obj) {
10220
10217
  if (obj !== dst) {
10221
- forEach(obj, function(value, key){
10218
+ forEach(obj, function(value, key) {
10222
10219
  dst[key] = value;
10223
10220
  });
10224
10221
  }
@@ -10241,7 +10238,7 @@ function inherit(parent, extra) {
10241
10238
  * @ngdoc function
10242
10239
  * @name angular.noop
10243
10240
  * @module ng
10244
- * @function
10241
+ * @kind function
10245
10242
  *
10246
10243
  * @description
10247
10244
  * A function that performs no operations. This function can be useful when writing code in the
@@ -10261,7 +10258,7 @@ noop.$inject = [];
10261
10258
  * @ngdoc function
10262
10259
  * @name angular.identity
10263
10260
  * @module ng
10264
- * @function
10261
+ * @kind function
10265
10262
  *
10266
10263
  * @description
10267
10264
  * A function that returns its first argument. This function is useful when writing code in the
@@ -10283,7 +10280,7 @@ function valueFn(value) {return function() {return value;};}
10283
10280
  * @ngdoc function
10284
10281
  * @name angular.isUndefined
10285
10282
  * @module ng
10286
- * @function
10283
+ * @kind function
10287
10284
  *
10288
10285
  * @description
10289
10286
  * Determines if a reference is undefined.
@@ -10298,7 +10295,7 @@ function isUndefined(value){return typeof value === 'undefined';}
10298
10295
  * @ngdoc function
10299
10296
  * @name angular.isDefined
10300
10297
  * @module ng
10301
- * @function
10298
+ * @kind function
10302
10299
  *
10303
10300
  * @description
10304
10301
  * Determines if a reference is defined.
@@ -10313,7 +10310,7 @@ function isDefined(value){return typeof value !== 'undefined';}
10313
10310
  * @ngdoc function
10314
10311
  * @name angular.isObject
10315
10312
  * @module ng
10316
- * @function
10313
+ * @kind function
10317
10314
  *
10318
10315
  * @description
10319
10316
  * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
@@ -10329,7 +10326,7 @@ function isObject(value){return value != null && typeof value === 'object';}
10329
10326
  * @ngdoc function
10330
10327
  * @name angular.isString
10331
10328
  * @module ng
10332
- * @function
10329
+ * @kind function
10333
10330
  *
10334
10331
  * @description
10335
10332
  * Determines if a reference is a `String`.
@@ -10344,7 +10341,7 @@ function isString(value){return typeof value === 'string';}
10344
10341
  * @ngdoc function
10345
10342
  * @name angular.isNumber
10346
10343
  * @module ng
10347
- * @function
10344
+ * @kind function
10348
10345
  *
10349
10346
  * @description
10350
10347
  * Determines if a reference is a `Number`.
@@ -10359,7 +10356,7 @@ function isNumber(value){return typeof value === 'number';}
10359
10356
  * @ngdoc function
10360
10357
  * @name angular.isDate
10361
10358
  * @module ng
10362
- * @function
10359
+ * @kind function
10363
10360
  *
10364
10361
  * @description
10365
10362
  * Determines if a value is a date.
@@ -10367,7 +10364,7 @@ function isNumber(value){return typeof value === 'number';}
10367
10364
  * @param {*} value Reference to check.
10368
10365
  * @returns {boolean} True if `value` is a `Date`.
10369
10366
  */
10370
- function isDate(value){
10367
+ function isDate(value) {
10371
10368
  return toString.call(value) === '[object Date]';
10372
10369
  }
10373
10370
 
@@ -10376,7 +10373,7 @@ function isDate(value){
10376
10373
  * @ngdoc function
10377
10374
  * @name angular.isArray
10378
10375
  * @module ng
10379
- * @function
10376
+ * @kind function
10380
10377
  *
10381
10378
  * @description
10382
10379
  * Determines if a reference is an `Array`.
@@ -10384,16 +10381,20 @@ function isDate(value){
10384
10381
  * @param {*} value Reference to check.
10385
10382
  * @returns {boolean} True if `value` is an `Array`.
10386
10383
  */
10387
- function isArray(value) {
10388
- return toString.call(value) === '[object Array]';
10389
- }
10390
-
10384
+ var isArray = (function() {
10385
+ if (!isFunction(Array.isArray)) {
10386
+ return function(value) {
10387
+ return toString.call(value) === '[object Array]';
10388
+ };
10389
+ }
10390
+ return Array.isArray;
10391
+ })();
10391
10392
 
10392
10393
  /**
10393
10394
  * @ngdoc function
10394
10395
  * @name angular.isFunction
10395
10396
  * @module ng
10396
- * @function
10397
+ * @kind function
10397
10398
  *
10398
10399
  * @description
10399
10400
  * Determines if a reference is a `Function`.
@@ -10467,7 +10468,7 @@ var trim = (function() {
10467
10468
  * @ngdoc function
10468
10469
  * @name angular.isElement
10469
10470
  * @module ng
10470
- * @function
10471
+ * @kind function
10471
10472
  *
10472
10473
  * @description
10473
10474
  * Determines if a reference is a DOM element (or wrapped jQuery element).
@@ -10485,7 +10486,7 @@ function isElement(node) {
10485
10486
  * @param str 'key1,key2,...'
10486
10487
  * @returns {object} in the form of {key1:true, key2:true, ...}
10487
10488
  */
10488
- function makeMap(str){
10489
+ function makeMap(str) {
10489
10490
  var obj = {}, items = str.split(","), i;
10490
10491
  for ( i = 0; i < items.length; i++ )
10491
10492
  obj[ items[i] ] = true;
@@ -10532,7 +10533,7 @@ function size(obj, ownPropsOnly) {
10532
10533
 
10533
10534
  if (isArray(obj) || isString(obj)) {
10534
10535
  return obj.length;
10535
- } else if (isObject(obj)){
10536
+ } else if (isObject(obj)) {
10536
10537
  for (key in obj)
10537
10538
  if (!ownPropsOnly || obj.hasOwnProperty(key))
10538
10539
  count++;
@@ -10578,7 +10579,7 @@ function isLeafNode (node) {
10578
10579
  * @ngdoc function
10579
10580
  * @name angular.copy
10580
10581
  * @module ng
10581
- * @function
10582
+ * @kind function
10582
10583
  *
10583
10584
  * @description
10584
10585
  * Creates a deep copy of `source`, which should be an object or an array.
@@ -10631,7 +10632,7 @@ function isLeafNode (node) {
10631
10632
  </file>
10632
10633
  </example>
10633
10634
  */
10634
- function copy(source, destination){
10635
+ function copy(source, destination, stackSource, stackDest) {
10635
10636
  if (isWindow(source) || isScope(source)) {
10636
10637
  throw ngMinErr('cpws',
10637
10638
  "Can't copy! Making copies of Window or Scope instances is not supported.");
@@ -10641,52 +10642,82 @@ function copy(source, destination){
10641
10642
  destination = source;
10642
10643
  if (source) {
10643
10644
  if (isArray(source)) {
10644
- destination = copy(source, []);
10645
+ destination = copy(source, [], stackSource, stackDest);
10645
10646
  } else if (isDate(source)) {
10646
10647
  destination = new Date(source.getTime());
10647
10648
  } else if (isRegExp(source)) {
10648
10649
  destination = new RegExp(source.source);
10649
10650
  } else if (isObject(source)) {
10650
- destination = copy(source, {});
10651
+ destination = copy(source, {}, stackSource, stackDest);
10651
10652
  }
10652
10653
  }
10653
10654
  } else {
10654
10655
  if (source === destination) throw ngMinErr('cpi',
10655
10656
  "Can't copy! Source and destination are identical.");
10657
+
10658
+ stackSource = stackSource || [];
10659
+ stackDest = stackDest || [];
10660
+
10661
+ if (isObject(source)) {
10662
+ var index = indexOf(stackSource, source);
10663
+ if (index !== -1) return stackDest[index];
10664
+
10665
+ stackSource.push(source);
10666
+ stackDest.push(destination);
10667
+ }
10668
+
10669
+ var result;
10656
10670
  if (isArray(source)) {
10657
10671
  destination.length = 0;
10658
10672
  for ( var i = 0; i < source.length; i++) {
10659
- destination.push(copy(source[i]));
10673
+ result = copy(source[i], null, stackSource, stackDest);
10674
+ if (isObject(source[i])) {
10675
+ stackSource.push(source[i]);
10676
+ stackDest.push(result);
10677
+ }
10678
+ destination.push(result);
10660
10679
  }
10661
10680
  } else {
10662
10681
  var h = destination.$$hashKey;
10663
- forEach(destination, function(value, key){
10682
+ forEach(destination, function(value, key) {
10664
10683
  delete destination[key];
10665
10684
  });
10666
10685
  for ( var key in source) {
10667
- destination[key] = copy(source[key]);
10686
+ result = copy(source[key], null, stackSource, stackDest);
10687
+ if (isObject(source[key])) {
10688
+ stackSource.push(source[key]);
10689
+ stackDest.push(result);
10690
+ }
10691
+ destination[key] = result;
10668
10692
  }
10669
10693
  setHashKey(destination,h);
10670
10694
  }
10695
+
10671
10696
  }
10672
10697
  return destination;
10673
10698
  }
10674
10699
 
10675
10700
  /**
10676
- * Create a shallow copy of an object
10701
+ * Creates a shallow copy of an object, an array or a primitive
10677
10702
  */
10678
10703
  function shallowCopy(src, dst) {
10679
- dst = dst || {};
10704
+ if (isArray(src)) {
10705
+ dst = dst || [];
10706
+
10707
+ for ( var i = 0; i < src.length; i++) {
10708
+ dst[i] = src[i];
10709
+ }
10710
+ } else if (isObject(src)) {
10711
+ dst = dst || {};
10680
10712
 
10681
- for(var key in src) {
10682
- // shallowCopy is only ever called by $compile nodeLinkFn, which has control over src
10683
- // so we don't need to worry about using our custom hasOwnProperty here
10684
- if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
10685
- dst[key] = src[key];
10713
+ for (var key in src) {
10714
+ if (hasOwnProperty.call(src, key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
10715
+ dst[key] = src[key];
10716
+ }
10686
10717
  }
10687
10718
  }
10688
10719
 
10689
- return dst;
10720
+ return dst || src;
10690
10721
  }
10691
10722
 
10692
10723
 
@@ -10694,7 +10725,7 @@ function shallowCopy(src, dst) {
10694
10725
  * @ngdoc function
10695
10726
  * @name angular.equals
10696
10727
  * @module ng
10697
- * @function
10728
+ * @kind function
10698
10729
  *
10699
10730
  * @description
10700
10731
  * Determines if two objects or two values are equivalent. Supports value types, regular
@@ -10706,7 +10737,7 @@ function shallowCopy(src, dst) {
10706
10737
  * * Both objects or values are of the same type and all of their properties are equal by
10707
10738
  * comparing them with `angular.equals`.
10708
10739
  * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
10709
- * * Both values represent the same regular expression (In JavasScript,
10740
+ * * Both values represent the same regular expression (In JavaScript,
10710
10741
  * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
10711
10742
  * representation matches).
10712
10743
  *
@@ -10781,7 +10812,7 @@ function sliceArgs(args, startIndex) {
10781
10812
  * @ngdoc function
10782
10813
  * @name angular.bind
10783
10814
  * @module ng
10784
- * @function
10815
+ * @kind function
10785
10816
  *
10786
10817
  * @description
10787
10818
  * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
@@ -10837,7 +10868,7 @@ function toJsonReplacer(key, value) {
10837
10868
  * @ngdoc function
10838
10869
  * @name angular.toJson
10839
10870
  * @module ng
10840
- * @function
10871
+ * @kind function
10841
10872
  *
10842
10873
  * @description
10843
10874
  * Serializes input into a JSON-formatted string. Properties with leading $ characters will be
@@ -10857,7 +10888,7 @@ function toJson(obj, pretty) {
10857
10888
  * @ngdoc function
10858
10889
  * @name angular.fromJson
10859
10890
  * @module ng
10860
- * @function
10891
+ * @kind function
10861
10892
  *
10862
10893
  * @description
10863
10894
  * Deserializes a JSON string.
@@ -10934,7 +10965,7 @@ function tryDecodeURIComponent(value) {
10934
10965
  */
10935
10966
  function parseKeyValue(/**string*/keyValue) {
10936
10967
  var obj = {}, key_value, key;
10937
- forEach((keyValue || "").split('&'), function(keyValue){
10968
+ forEach((keyValue || "").split('&'), function(keyValue) {
10938
10969
  if ( keyValue ) {
10939
10970
  key_value = keyValue.split('=');
10940
10971
  key = tryDecodeURIComponent(key_value[0]);
@@ -11196,7 +11227,7 @@ function bootstrap(element, modules) {
11196
11227
  }
11197
11228
 
11198
11229
  var SNAKE_CASE_REGEXP = /[A-Z]/g;
11199
- function snake_case(name, separator){
11230
+ function snake_case(name, separator) {
11200
11231
  separator = separator || '_';
11201
11232
  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
11202
11233
  return (pos ? separator : '') + letter.toLowerCase();
@@ -11206,8 +11237,9 @@ function snake_case(name, separator){
11206
11237
  function bindJQuery() {
11207
11238
  // bind to jQuery if present;
11208
11239
  jQuery = window.jQuery;
11209
- // reset to jQuery or default to us.
11210
- if (jQuery) {
11240
+ // Use jQuery if it exists with proper functionality, otherwise default to us.
11241
+ // Angular 1.2+ requires jQuery 1.7.1+ for on()/off() support.
11242
+ if (jQuery && jQuery.fn.on) {
11211
11243
  jqLite = jQuery;
11212
11244
  extend(jQuery.fn, {
11213
11245
  scope: JQLitePrototype.scope,
@@ -11353,7 +11385,7 @@ function setupModuleLoader(window) {
11353
11385
  *
11354
11386
  * # Module
11355
11387
  *
11356
- * A module is a collection of services, directives, filters, and configuration information.
11388
+ * A module is a collection of services, directives, controllers, filters, and configuration information.
11357
11389
  * `angular.module` is used to configure the {@link auto.$injector $injector}.
11358
11390
  *
11359
11391
  * ```js
@@ -11381,9 +11413,9 @@ function setupModuleLoader(window) {
11381
11413
  * {@link angular.bootstrap} to simplify this process for you.
11382
11414
  *
11383
11415
  * @param {!string} name The name of the module to create or retrieve.
11384
- <<<<<* @param {!Array.<string>=} requires If specified then new module is being created. If
11385
- >>>>>* unspecified then the module is being retrieved for further configuration.
11386
- * @param {Function} configFn Optional configuration function for the module. Same as
11416
+ * @param {!Array.<string>=} requires If specified then new module is being created. If
11417
+ * unspecified then the module is being retrieved for further configuration.
11418
+ * @param {Function=} configFn Optional configuration function for the module. Same as
11387
11419
  * {@link angular.Module#config Module#config()}.
11388
11420
  * @returns {module} new module with the {@link angular.Module} api.
11389
11421
  */
@@ -11575,6 +11607,8 @@ function setupModuleLoader(window) {
11575
11607
  * configuration.
11576
11608
  * @description
11577
11609
  * Use this method to register work which needs to be performed on module loading.
11610
+ * For more about how to configure services, see
11611
+ * {@link providers#providers_provider-recipe Provider Recipe}.
11578
11612
  */
11579
11613
  config: config,
11580
11614
 
@@ -11711,11 +11745,11 @@ function setupModuleLoader(window) {
11711
11745
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
11712
11746
  */
11713
11747
  var version = {
11714
- full: '1.2.16', // all of these placeholder strings will be replaced by grunt's
11748
+ full: '1.2.18', // all of these placeholder strings will be replaced by grunt's
11715
11749
  major: 1, // package task
11716
11750
  minor: 2,
11717
- dot: 16,
11718
- codeName: 'badger-enumeration'
11751
+ dot: 18,
11752
+ codeName: 'ear-extendability'
11719
11753
  };
11720
11754
 
11721
11755
 
@@ -11855,7 +11889,7 @@ function publishExternalAPI(angular){
11855
11889
  * @ngdoc function
11856
11890
  * @name angular.element
11857
11891
  * @module ng
11858
- * @function
11892
+ * @kind function
11859
11893
  *
11860
11894
  * @description
11861
11895
  * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
@@ -11938,7 +11972,7 @@ function publishExternalAPI(angular){
11938
11972
  */
11939
11973
 
11940
11974
  var jqCache = JQLite.cache = {},
11941
- jqName = JQLite.expando = 'ng-' + new Date().getTime(),
11975
+ jqName = JQLite.expando = 'ng' + new Date().getTime(),
11942
11976
  jqId = 1,
11943
11977
  addEventListenerFn = (window.document.addEventListener
11944
11978
  ? function(element, type, fn) {element.addEventListener(type, fn, false);}
@@ -12491,6 +12525,7 @@ forEach({
12491
12525
  */
12492
12526
  JQLite.prototype[name] = function(arg1, arg2) {
12493
12527
  var i, key;
12528
+ var nodeCount = this.length;
12494
12529
 
12495
12530
  // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
12496
12531
  // in a way that survives minification.
@@ -12500,7 +12535,7 @@ forEach({
12500
12535
  if (isObject(arg1)) {
12501
12536
 
12502
12537
  // we are a write, but the object properties are the key/values
12503
- for (i = 0; i < this.length; i++) {
12538
+ for (i = 0; i < nodeCount; i++) {
12504
12539
  if (fn === jqLiteData) {
12505
12540
  // data() takes the whole object in jQuery
12506
12541
  fn(this[i], arg1);
@@ -12514,9 +12549,10 @@ forEach({
12514
12549
  return this;
12515
12550
  } else {
12516
12551
  // we are a read, so read the first child.
12552
+ // TODO: do we still need this?
12517
12553
  var value = fn.$dv;
12518
12554
  // Only if we have $dv do we iterate over all, otherwise it is just the first element.
12519
- var jj = (value === undefined) ? Math.min(this.length, 1) : this.length;
12555
+ var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;
12520
12556
  for (var j = 0; j < jj; j++) {
12521
12557
  var nodeValue = fn(this[j], arg1, arg2);
12522
12558
  value = value ? value + nodeValue : nodeValue;
@@ -12525,7 +12561,7 @@ forEach({
12525
12561
  }
12526
12562
  } else {
12527
12563
  // we are a write, so apply to all children
12528
- for (i = 0; i < this.length; i++) {
12564
+ for (i = 0; i < nodeCount; i++) {
12529
12565
  fn(this[i], arg1, arg2);
12530
12566
  }
12531
12567
  // return self for chaining
@@ -12894,7 +12930,7 @@ HashMap.prototype = {
12894
12930
  * @ngdoc function
12895
12931
  * @module ng
12896
12932
  * @name angular.injector
12897
- * @function
12933
+ * @kind function
12898
12934
  *
12899
12935
  * @description
12900
12936
  * Creates an injector function that can be used for retrieving services as well as for
@@ -12921,7 +12957,7 @@ HashMap.prototype = {
12921
12957
  *
12922
12958
  * Sometimes you want to get access to the injector of a currently running Angular app
12923
12959
  * from outside Angular. Perhaps, you want to inject and compile some markup after the
12924
- * application has been bootstrapped. You can do this using extra `injector()` added
12960
+ * application has been bootstrapped. You can do this using the extra `injector()` added
12925
12961
  * to JQuery/jqLite elements. See {@link angular.element}.
12926
12962
  *
12927
12963
  * *This is fairly rare but could be the case if a third party library is injecting the
@@ -12991,7 +13027,7 @@ function annotate(fn) {
12991
13027
  /**
12992
13028
  * @ngdoc service
12993
13029
  * @name $injector
12994
- * @function
13030
+ * @kind function
12995
13031
  *
12996
13032
  * @description
12997
13033
  *
@@ -13034,7 +13070,7 @@ function annotate(fn) {
13034
13070
  * minification, and obfuscation tools since these tools change the argument names.
13035
13071
  *
13036
13072
  * ## `$inject` Annotation
13037
- * By adding a `$inject` property onto a function the injection parameters can be specified.
13073
+ * By adding an `$inject` property onto a function the injection parameters can be specified.
13038
13074
  *
13039
13075
  * ## Inline
13040
13076
  * As an array of injection names, where the last item in the array is the function to call.
@@ -13071,7 +13107,7 @@ function annotate(fn) {
13071
13107
  * @name $injector#has
13072
13108
  *
13073
13109
  * @description
13074
- * Allows the user to query if the particular service exist.
13110
+ * Allows the user to query if the particular service exists.
13075
13111
  *
13076
13112
  * @param {string} Name of the service to query.
13077
13113
  * @returns {boolean} returns true if injector has given service.
@@ -13081,8 +13117,8 @@ function annotate(fn) {
13081
13117
  * @ngdoc method
13082
13118
  * @name $injector#instantiate
13083
13119
  * @description
13084
- * Create a new instance of JS type. The method takes a constructor function invokes the new
13085
- * operator and supplies all of the arguments to the constructor function as specified by the
13120
+ * Create a new instance of JS type. The method takes a constructor function, invokes the new
13121
+ * operator, and supplies all of the arguments to the constructor function as specified by the
13086
13122
  * constructor annotation.
13087
13123
  *
13088
13124
  * @param {Function} Type Annotated constructor function.
@@ -13614,7 +13650,8 @@ function createInjector(modulesToLoad) {
13614
13650
  function getService(serviceName) {
13615
13651
  if (cache.hasOwnProperty(serviceName)) {
13616
13652
  if (cache[serviceName] === INSTANTIATING) {
13617
- throw $injectorMinErr('cdep', 'Circular dependency found: {0}', path.join(' <- '));
13653
+ throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
13654
+ serviceName + ' <- ' + path.join(' <- '));
13618
13655
  }
13619
13656
  return cache[serviceName];
13620
13657
  } else {
@@ -13695,7 +13732,7 @@ function createInjector(modulesToLoad) {
13695
13732
  * @requires $rootScope
13696
13733
  *
13697
13734
  * @description
13698
- * When called, it checks current value of `$location.hash()` and scroll to related element,
13735
+ * When called, it checks current value of `$location.hash()` and scrolls to the related element,
13699
13736
  * according to rules specified in
13700
13737
  * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).
13701
13738
  *
@@ -13897,7 +13934,7 @@ var $AnimateProvider = ['$provide', function($provide) {
13897
13934
  *
13898
13935
  * @ngdoc method
13899
13936
  * @name $animate#enter
13900
- * @function
13937
+ * @kind function
13901
13938
  * @description Inserts the element into the DOM either after the `after` element or within
13902
13939
  * the `parent` element. Once complete, the done() callback will be fired (if provided).
13903
13940
  * @param {DOMElement} element the element which will be inserted into the DOM
@@ -13924,7 +13961,7 @@ var $AnimateProvider = ['$provide', function($provide) {
13924
13961
  *
13925
13962
  * @ngdoc method
13926
13963
  * @name $animate#leave
13927
- * @function
13964
+ * @kind function
13928
13965
  * @description Removes the element from the DOM. Once complete, the done() callback will be
13929
13966
  * fired (if provided).
13930
13967
  * @param {DOMElement} element the element which will be removed from the DOM
@@ -13940,7 +13977,7 @@ var $AnimateProvider = ['$provide', function($provide) {
13940
13977
  *
13941
13978
  * @ngdoc method
13942
13979
  * @name $animate#move
13943
- * @function
13980
+ * @kind function
13944
13981
  * @description Moves the position of the provided element within the DOM to be placed
13945
13982
  * either after the `after` element or inside of the `parent` element. Once complete, the
13946
13983
  * done() callback will be fired (if provided).
@@ -13964,7 +14001,7 @@ var $AnimateProvider = ['$provide', function($provide) {
13964
14001
  *
13965
14002
  * @ngdoc method
13966
14003
  * @name $animate#addClass
13967
- * @function
14004
+ * @kind function
13968
14005
  * @description Adds the provided className CSS class value to the provided element. Once
13969
14006
  * complete, the done() callback will be fired (if provided).
13970
14007
  * @param {DOMElement} element the element which will have the className value
@@ -13987,7 +14024,7 @@ var $AnimateProvider = ['$provide', function($provide) {
13987
14024
  *
13988
14025
  * @ngdoc method
13989
14026
  * @name $animate#removeClass
13990
- * @function
14027
+ * @kind function
13991
14028
  * @description Removes the provided className CSS class value from the provided element.
13992
14029
  * Once complete, the done() callback will be fired (if provided).
13993
14030
  * @param {DOMElement} element the element which will have the className value
@@ -14010,10 +14047,10 @@ var $AnimateProvider = ['$provide', function($provide) {
14010
14047
  *
14011
14048
  * @ngdoc method
14012
14049
  * @name $animate#setClass
14013
- * @function
14050
+ * @kind function
14014
14051
  * @description Adds and/or removes the given CSS classes to and from the element.
14015
14052
  * Once complete, the done() callback will be fired (if provided).
14016
- * @param {DOMElement} element the element which will it's CSS classes changed
14053
+ * @param {DOMElement} element the element which will have its CSS classes changed
14017
14054
  * removed from it
14018
14055
  * @param {string} add the CSS classes which will be added to the element
14019
14056
  * @param {string} remove the CSS class which will be removed from the element
@@ -14567,7 +14604,7 @@ function $CacheFactoryProvider() {
14567
14604
  /**
14568
14605
  * @ngdoc method
14569
14606
  * @name $cacheFactory.Cache#put
14570
- * @function
14607
+ * @kind function
14571
14608
  *
14572
14609
  * @description
14573
14610
  * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be
@@ -14603,7 +14640,7 @@ function $CacheFactoryProvider() {
14603
14640
  /**
14604
14641
  * @ngdoc method
14605
14642
  * @name $cacheFactory.Cache#get
14606
- * @function
14643
+ * @kind function
14607
14644
  *
14608
14645
  * @description
14609
14646
  * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.
@@ -14627,7 +14664,7 @@ function $CacheFactoryProvider() {
14627
14664
  /**
14628
14665
  * @ngdoc method
14629
14666
  * @name $cacheFactory.Cache#remove
14630
- * @function
14667
+ * @kind function
14631
14668
  *
14632
14669
  * @description
14633
14670
  * Removes an entry from the {@link $cacheFactory.Cache Cache} object.
@@ -14655,7 +14692,7 @@ function $CacheFactoryProvider() {
14655
14692
  /**
14656
14693
  * @ngdoc method
14657
14694
  * @name $cacheFactory.Cache#removeAll
14658
- * @function
14695
+ * @kind function
14659
14696
  *
14660
14697
  * @description
14661
14698
  * Clears the cache object of any entries.
@@ -14671,7 +14708,7 @@ function $CacheFactoryProvider() {
14671
14708
  /**
14672
14709
  * @ngdoc method
14673
14710
  * @name $cacheFactory.Cache#destroy
14674
- * @function
14711
+ * @kind function
14675
14712
  *
14676
14713
  * @description
14677
14714
  * Destroys the {@link $cacheFactory.Cache Cache} object entirely,
@@ -14688,7 +14725,7 @@ function $CacheFactoryProvider() {
14688
14725
  /**
14689
14726
  * @ngdoc method
14690
14727
  * @name $cacheFactory.Cache#info
14691
- * @function
14728
+ * @kind function
14692
14729
  *
14693
14730
  * @description
14694
14731
  * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.
@@ -14743,7 +14780,7 @@ function $CacheFactoryProvider() {
14743
14780
  * @name $cacheFactory#info
14744
14781
  *
14745
14782
  * @description
14746
- * Get information about all the of the caches that have been created
14783
+ * Get information about all the caches that have been created
14747
14784
  *
14748
14785
  * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`
14749
14786
  */
@@ -14844,7 +14881,7 @@ function $TemplateCacheProvider() {
14844
14881
  /**
14845
14882
  * @ngdoc service
14846
14883
  * @name $compile
14847
- * @function
14884
+ * @kind function
14848
14885
  *
14849
14886
  * @description
14850
14887
  * Compiles an HTML string or DOM into a template and produces a template function, which
@@ -14882,7 +14919,6 @@ function $TemplateCacheProvider() {
14882
14919
  * template: '<div></div>', // or // function(tElement, tAttrs) { ... },
14883
14920
  * // or
14884
14921
  * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
14885
- * replace: false,
14886
14922
  * transclude: false,
14887
14923
  * restrict: 'A',
14888
14924
  * scope: false,
@@ -15058,7 +15094,7 @@ function $TemplateCacheProvider() {
15058
15094
  * api/ng.$sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.
15059
15095
  *
15060
15096
  *
15061
- * #### `replace`
15097
+ * #### `replace` ([*DEPRECATED*!], will be removed in next major release)
15062
15098
  * specify where the template should be inserted. Defaults to `false`.
15063
15099
  *
15064
15100
  * * `true` - the template will replace the current element.
@@ -15085,11 +15121,7 @@ function $TemplateCacheProvider() {
15085
15121
  * ```
15086
15122
  *
15087
15123
  * The compile function deals with transforming the template DOM. Since most directives do not do
15088
- * template transformation, it is not used often. Examples that require compile functions are
15089
- * directives that transform template DOM, such as {@link
15090
- * api/ng.directive:ngRepeat ngRepeat}, or load the contents
15091
- * asynchronously, such as {@link ngRoute.directive:ngView ngView}. The
15092
- * compile function takes the following arguments.
15124
+ * template transformation, it is not used often. The compile function takes the following arguments:
15093
15125
  *
15094
15126
  * * `tElement` - template element - The element where the directive has been declared. It is
15095
15127
  * safe to do template transformation on the element and child elements only.
@@ -15327,7 +15359,7 @@ var $compileMinErr = minErr('$compile');
15327
15359
  /**
15328
15360
  * @ngdoc provider
15329
15361
  * @name $compileProvider
15330
- * @function
15362
+ * @kind function
15331
15363
  *
15332
15364
  * @description
15333
15365
  */
@@ -15335,8 +15367,8 @@ $CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
15335
15367
  function $CompileProvider($provide, $$sanitizeUriProvider) {
15336
15368
  var hasDirectives = {},
15337
15369
  Suffix = 'Directive',
15338
- COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
15339
- CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/;
15370
+ COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w_\-]+)\s+(.*)$/,
15371
+ CLASS_DIRECTIVE_REGEXP = /(([\d\w_\-]+)(?:\:([^;]+))?;?)/;
15340
15372
 
15341
15373
  // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
15342
15374
  // The assumption is that future DOM event attribute names will begin with
@@ -15346,7 +15378,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15346
15378
  /**
15347
15379
  * @ngdoc method
15348
15380
  * @name $compileProvider#directive
15349
- * @function
15381
+ * @kind function
15350
15382
  *
15351
15383
  * @description
15352
15384
  * Register a new directive with the compiler.
@@ -15399,7 +15431,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15399
15431
  /**
15400
15432
  * @ngdoc method
15401
15433
  * @name $compileProvider#aHrefSanitizationWhitelist
15402
- * @function
15434
+ * @kind function
15403
15435
  *
15404
15436
  * @description
15405
15437
  * Retrieves or overrides the default regular expression that is used for whitelisting of safe
@@ -15429,7 +15461,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15429
15461
  /**
15430
15462
  * @ngdoc method
15431
15463
  * @name $compileProvider#imgSrcSanitizationWhitelist
15432
- * @function
15464
+ * @kind function
15433
15465
  *
15434
15466
  * @description
15435
15467
  * Retrieves or overrides the default regular expression that is used for whitelisting of safe
@@ -15473,7 +15505,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15473
15505
  /**
15474
15506
  * @ngdoc method
15475
15507
  * @name $compile.directive.Attributes#$addClass
15476
- * @function
15508
+ * @kind function
15477
15509
  *
15478
15510
  * @description
15479
15511
  * Adds the CSS class value specified by the classVal parameter to the element. If animations
@@ -15490,7 +15522,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15490
15522
  /**
15491
15523
  * @ngdoc method
15492
15524
  * @name $compile.directive.Attributes#$removeClass
15493
- * @function
15525
+ * @kind function
15494
15526
  *
15495
15527
  * @description
15496
15528
  * Removes the CSS class value specified by the classVal parameter from the element. If
@@ -15507,7 +15539,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15507
15539
  /**
15508
15540
  * @ngdoc method
15509
15541
  * @name $compile.directive.Attributes#$updateClass
15510
- * @function
15542
+ * @kind function
15511
15543
  *
15512
15544
  * @description
15513
15545
  * Adds and removes the appropriate CSS class values to the element based on the difference
@@ -15595,7 +15627,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15595
15627
  /**
15596
15628
  * @ngdoc method
15597
15629
  * @name $compile.directive.Attributes#$observe
15598
- * @function
15630
+ * @kind function
15599
15631
  *
15600
15632
  * @description
15601
15633
  * Observes an interpolated attribute.
@@ -15658,7 +15690,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15658
15690
  compileNodes($compileNodes, transcludeFn, $compileNodes,
15659
15691
  maxPriority, ignoreDirective, previousCompileContext);
15660
15692
  safeAddClass($compileNodes, 'ng-scope');
15661
- return function publicLinkFn(scope, cloneConnectFn, transcludeControllers){
15693
+ return function publicLinkFn(scope, cloneConnectFn, transcludeControllers, parentBoundTranscludeFn){
15662
15694
  assertArg(scope, 'scope');
15663
15695
  // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
15664
15696
  // and sometimes changes the structure of the DOM.
@@ -15680,7 +15712,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15680
15712
  }
15681
15713
 
15682
15714
  if (cloneConnectFn) cloneConnectFn($linkNode, scope);
15683
- if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);
15715
+ if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);
15684
15716
  return $linkNode;
15685
15717
  };
15686
15718
  }
@@ -15735,7 +15767,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15735
15767
  !childNodes.length)
15736
15768
  ? null
15737
15769
  : compileNodes(childNodes,
15738
- nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
15770
+ nodeLinkFn ? (
15771
+ (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)
15772
+ && nodeLinkFn.transclude) : transcludeFn);
15739
15773
 
15740
15774
  linkFns.push(nodeLinkFn, childLinkFn);
15741
15775
  linkFnFound = linkFnFound || nodeLinkFn || childLinkFn;
@@ -15746,8 +15780,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15746
15780
  // return a linking function if we have found anything, null otherwise
15747
15781
  return linkFnFound ? compositeLinkFn : null;
15748
15782
 
15749
- function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
15750
- var nodeLinkFn, childLinkFn, node, $node, childScope, childTranscludeFn, i, ii, n;
15783
+ function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {
15784
+ var nodeLinkFn, childLinkFn, node, $node, childScope, i, ii, n, childBoundTranscludeFn;
15751
15785
 
15752
15786
  // copy nodeList so that linking doesn't break due to live list updates.
15753
15787
  var nodeListLength = nodeList.length,
@@ -15769,23 +15803,32 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15769
15803
  } else {
15770
15804
  childScope = scope;
15771
15805
  }
15772
- childTranscludeFn = nodeLinkFn.transclude;
15773
- if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {
15774
- nodeLinkFn(childLinkFn, childScope, node, $rootElement,
15775
- createBoundTranscludeFn(scope, childTranscludeFn || transcludeFn)
15776
- );
15806
+
15807
+ if ( nodeLinkFn.transcludeOnThisElement ) {
15808
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude, parentBoundTranscludeFn);
15809
+
15810
+ } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
15811
+ childBoundTranscludeFn = parentBoundTranscludeFn;
15812
+
15813
+ } else if (!parentBoundTranscludeFn && transcludeFn) {
15814
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);
15815
+
15777
15816
  } else {
15778
- nodeLinkFn(childLinkFn, childScope, node, $rootElement, boundTranscludeFn);
15817
+ childBoundTranscludeFn = null;
15779
15818
  }
15819
+
15820
+ nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
15821
+
15780
15822
  } else if (childLinkFn) {
15781
- childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
15823
+ childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);
15782
15824
  }
15783
15825
  }
15784
15826
  }
15785
15827
  }
15786
15828
 
15787
- function createBoundTranscludeFn(scope, transcludeFn) {
15788
- return function boundTranscludeFn(transcludedScope, cloneFn, controllers) {
15829
+ function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {
15830
+
15831
+ var boundTranscludeFn = function(transcludedScope, cloneFn, controllers) {
15789
15832
  var scopeCreated = false;
15790
15833
 
15791
15834
  if (!transcludedScope) {
@@ -15794,12 +15837,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15794
15837
  scopeCreated = true;
15795
15838
  }
15796
15839
 
15797
- var clone = transcludeFn(transcludedScope, cloneFn, controllers);
15840
+ var clone = transcludeFn(transcludedScope, cloneFn, controllers, previousBoundTranscludeFn);
15798
15841
  if (scopeCreated) {
15799
- clone.on('$destroy', bind(transcludedScope, transcludedScope.$destroy));
15842
+ clone.on('$destroy', function() { transcludedScope.$destroy(); });
15800
15843
  }
15801
15844
  return clone;
15802
15845
  };
15846
+
15847
+ return boundTranscludeFn;
15803
15848
  }
15804
15849
 
15805
15850
  /**
@@ -15977,6 +16022,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15977
16022
  templateDirective = previousCompileContext.templateDirective,
15978
16023
  nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
15979
16024
  hasTranscludeDirective = false,
16025
+ hasTemplate = false,
15980
16026
  hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,
15981
16027
  $compileNode = templateAttrs.$$element = jqLite(compileNode),
15982
16028
  directive,
@@ -16067,6 +16113,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16067
16113
  }
16068
16114
 
16069
16115
  if (directive.template) {
16116
+ hasTemplate = true;
16070
16117
  assertNoDuplicate('template', templateDirective, directive, $compileNode);
16071
16118
  templateDirective = directive;
16072
16119
 
@@ -16081,7 +16128,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16081
16128
  if (jqLiteIsTextNode(directiveValue)) {
16082
16129
  $template = [];
16083
16130
  } else {
16084
- $template = jqLite(directiveValue);
16131
+ $template = jqLite(trim(directiveValue));
16085
16132
  }
16086
16133
  compileNode = $template[0];
16087
16134
 
@@ -16116,6 +16163,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16116
16163
  }
16117
16164
 
16118
16165
  if (directive.templateUrl) {
16166
+ hasTemplate = true;
16119
16167
  assertNoDuplicate('template', templateDirective, directive, $compileNode);
16120
16168
  templateDirective = directive;
16121
16169
 
@@ -16124,7 +16172,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16124
16172
  }
16125
16173
 
16126
16174
  nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
16127
- templateAttrs, jqCollection, childTranscludeFn, preLinkFns, postLinkFns, {
16175
+ templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {
16128
16176
  controllerDirectives: controllerDirectives,
16129
16177
  newIsolateScopeDirective: newIsolateScopeDirective,
16130
16178
  templateDirective: templateDirective,
@@ -16152,7 +16200,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16152
16200
  }
16153
16201
 
16154
16202
  nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
16155
- nodeLinkFn.transclude = hasTranscludeDirective && childTranscludeFn;
16203
+ nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
16204
+ nodeLinkFn.templateOnThisElement = hasTemplate;
16205
+ nodeLinkFn.transclude = childTranscludeFn;
16206
+
16156
16207
  previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
16157
16208
 
16158
16209
  // might be normal or delayed nodeLinkFn depending on if templateUrl is present
@@ -16164,6 +16215,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16164
16215
  if (pre) {
16165
16216
  if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);
16166
16217
  pre.require = directive.require;
16218
+ pre.directiveName = directiveName;
16167
16219
  if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
16168
16220
  pre = cloneAndAnnotateFn(pre, {isolateScope: true});
16169
16221
  }
@@ -16172,6 +16224,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16172
16224
  if (post) {
16173
16225
  if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);
16174
16226
  post.require = directive.require;
16227
+ post.directiveName = directiveName;
16175
16228
  if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
16176
16229
  post = cloneAndAnnotateFn(post, {isolateScope: true});
16177
16230
  }
@@ -16180,7 +16233,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16180
16233
  }
16181
16234
 
16182
16235
 
16183
- function getControllers(require, $element, elementControllers) {
16236
+ function getControllers(directiveName, require, $element, elementControllers) {
16184
16237
  var value, retrievalMethod = 'data', optional = false;
16185
16238
  if (isString(require)) {
16186
16239
  while((value = require.charAt(0)) == '^' || value == '?') {
@@ -16206,7 +16259,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16206
16259
  } else if (isArray(require)) {
16207
16260
  value = [];
16208
16261
  forEach(require, function(require) {
16209
- value.push(getControllers(require, $element, elementControllers));
16262
+ value.push(getControllers(directiveName, require, $element, elementControllers));
16210
16263
  });
16211
16264
  }
16212
16265
  return value;
@@ -16229,7 +16282,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16229
16282
 
16230
16283
  isolateScope = scope.$new(true);
16231
16284
 
16232
- if (templateDirective && (templateDirective === newIsolateScopeDirective.$$originalDirective)) {
16285
+ if (templateDirective && (templateDirective === newIsolateScopeDirective ||
16286
+ templateDirective === newIsolateScopeDirective.$$originalDirective)) {
16233
16287
  $linkNode.data('$isolateScope', isolateScope) ;
16234
16288
  } else {
16235
16289
  $linkNode.data('$isolateScopeNoTemplate', isolateScope);
@@ -16349,7 +16403,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16349
16403
  try {
16350
16404
  linkFn = preLinkFns[i];
16351
16405
  linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
16352
- linkFn.require && getControllers(linkFn.require, $element, elementControllers), transcludeFn);
16406
+ linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn);
16353
16407
  } catch (e) {
16354
16408
  $exceptionHandler(e, startingTag($element));
16355
16409
  }
@@ -16369,7 +16423,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16369
16423
  try {
16370
16424
  linkFn = postLinkFns[i];
16371
16425
  linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
16372
- linkFn.require && getControllers(linkFn.require, $element, elementControllers), transcludeFn);
16426
+ linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn);
16373
16427
  } catch (e) {
16374
16428
  $exceptionHandler(e, startingTag($element));
16375
16429
  }
@@ -16455,7 +16509,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16455
16509
  // reapply the old attributes to the new element
16456
16510
  forEach(dst, function(value, key) {
16457
16511
  if (key.charAt(0) != '$') {
16458
- if (src[key]) {
16512
+ if (src[key] && src[key] !== value) {
16459
16513
  value += (key === 'style' ? ';' : ' ') + src[key];
16460
16514
  }
16461
16515
  dst.$set(key, value, true, srcAttr[key]);
@@ -16508,7 +16562,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16508
16562
  if (jqLiteIsTextNode(content)) {
16509
16563
  $template = [];
16510
16564
  } else {
16511
- $template = jqLite(content);
16565
+ $template = jqLite(trim(content));
16512
16566
  }
16513
16567
  compileNode = $template[0];
16514
16568
 
@@ -16544,7 +16598,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16544
16598
  });
16545
16599
  afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
16546
16600
 
16547
-
16548
16601
  while(linkQueue.length) {
16549
16602
  var scope = linkQueue.shift(),
16550
16603
  beforeTemplateLinkNode = linkQueue.shift(),
@@ -16566,8 +16619,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16566
16619
  // Copy in CSS classes from original node
16567
16620
  safeAddClass(jqLite(linkNode), oldClasses);
16568
16621
  }
16569
- if (afterTemplateNodeLinkFn.transclude) {
16570
- childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude);
16622
+ if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
16623
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
16571
16624
  } else {
16572
16625
  childBoundTranscludeFn = boundTranscludeFn;
16573
16626
  }
@@ -16581,13 +16634,17 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16581
16634
  });
16582
16635
 
16583
16636
  return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
16637
+ var childBoundTranscludeFn = boundTranscludeFn;
16584
16638
  if (linkQueue) {
16585
16639
  linkQueue.push(scope);
16586
16640
  linkQueue.push(node);
16587
16641
  linkQueue.push(rootElement);
16588
- linkQueue.push(boundTranscludeFn);
16642
+ linkQueue.push(childBoundTranscludeFn);
16589
16643
  } else {
16590
- afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, boundTranscludeFn);
16644
+ if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
16645
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
16646
+ }
16647
+ afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);
16591
16648
  }
16592
16649
  };
16593
16650
  }
@@ -16612,23 +16669,31 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16612
16669
  }
16613
16670
 
16614
16671
 
16615
- function addTextInterpolateDirective(directives, text) {
16616
- var interpolateFn = $interpolate(text, true);
16617
- if (interpolateFn) {
16618
- directives.push({
16619
- priority: 0,
16620
- compile: valueFn(function textInterpolateLinkFn(scope, node) {
16621
- var parent = node.parent(),
16622
- bindings = parent.data('$binding') || [];
16623
- bindings.push(interpolateFn);
16624
- safeAddClass(parent.data('$binding', bindings), 'ng-binding');
16625
- scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
16626
- node[0].nodeValue = value;
16627
- });
16628
- })
16629
- });
16672
+ function addTextInterpolateDirective(directives, text) {
16673
+ var interpolateFn = $interpolate(text, true);
16674
+ if (interpolateFn) {
16675
+ directives.push({
16676
+ priority: 0,
16677
+ compile: function textInterpolateCompileFn(templateNode) {
16678
+ // when transcluding a template that has bindings in the root
16679
+ // then we don't have a parent and should do this in the linkFn
16680
+ var parent = templateNode.parent(), hasCompileParent = parent.length;
16681
+ if (hasCompileParent) safeAddClass(templateNode.parent(), 'ng-binding');
16682
+
16683
+ return function textInterpolateLinkFn(scope, node) {
16684
+ var parent = node.parent(),
16685
+ bindings = parent.data('$binding') || [];
16686
+ bindings.push(interpolateFn);
16687
+ parent.data('$binding', bindings);
16688
+ if (!hasCompileParent) safeAddClass(parent, 'ng-binding');
16689
+ scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
16690
+ node[0].nodeValue = value;
16691
+ });
16692
+ };
16693
+ }
16694
+ });
16695
+ }
16630
16696
  }
16631
- }
16632
16697
 
16633
16698
 
16634
16699
  function getTrustedContext(node, attrNormalizedName) {
@@ -16789,7 +16854,9 @@ function directiveNormalize(name) {
16789
16854
  * element attributes. The values reflect current binding state `{{ }}`. The normalization is
16790
16855
  * needed since all of these are treated as equivalent in Angular:
16791
16856
  *
16857
+ * ```
16792
16858
  * <span ng:bind="a" ng-bind="a" data-ng-bind="a" x-ng-bind="a">
16859
+ * ```
16793
16860
  */
16794
16861
 
16795
16862
  /**
@@ -16803,7 +16870,7 @@ function directiveNormalize(name) {
16803
16870
  /**
16804
16871
  * @ngdoc method
16805
16872
  * @name $compile.directive.Attributes#$set
16806
- * @function
16873
+ * @kind function
16807
16874
  *
16808
16875
  * @description
16809
16876
  * Set DOM element attribute value.
@@ -17121,9 +17188,9 @@ function $HttpProvider() {
17121
17188
  common: {
17122
17189
  'Accept': 'application/json, text/plain, */*'
17123
17190
  },
17124
- post: copy(CONTENT_TYPE_APPLICATION_JSON),
17125
- put: copy(CONTENT_TYPE_APPLICATION_JSON),
17126
- patch: copy(CONTENT_TYPE_APPLICATION_JSON)
17191
+ post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
17192
+ put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
17193
+ patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON)
17127
17194
  },
17128
17195
 
17129
17196
  xsrfCookieName: 'XSRF-TOKEN',
@@ -17365,14 +17432,14 @@ function $HttpProvider() {
17365
17432
  *
17366
17433
  * There are two kinds of interceptors (and two kinds of rejection interceptors):
17367
17434
  *
17368
- * * `request`: interceptors get called with http `config` object. The function is free to
17369
- * modify the `config` or create a new one. The function needs to return the `config`
17370
- * directly or as a promise.
17435
+ * * `request`: interceptors get called with a http `config` object. The function is free to
17436
+ * modify the `config` object or create a new one. The function needs to return the `config`
17437
+ * object directly, or a promise containing the `config` or a new `config` object.
17371
17438
  * * `requestError`: interceptor gets called when a previous interceptor threw an error or
17372
17439
  * resolved with a rejection.
17373
17440
  * * `response`: interceptors get called with http `response` object. The function is free to
17374
- * modify the `response` or create a new one. The function needs to return the `response`
17375
- * directly or as a promise.
17441
+ * modify the `response` object or create a new one. The function needs to return the `response`
17442
+ * object directly, or as a promise containing the `response` or a new `response` object.
17376
17443
  * * `responseError`: interceptor gets called when a previous interceptor threw an error or
17377
17444
  * resolved with a rejection.
17378
17445
  *
@@ -17384,7 +17451,7 @@ function $HttpProvider() {
17384
17451
  * // optional method
17385
17452
  * 'request': function(config) {
17386
17453
  * // do something on success
17387
- * return config || $q.when(config);
17454
+ * return config;
17388
17455
  * },
17389
17456
  *
17390
17457
  * // optional method
@@ -17401,7 +17468,7 @@ function $HttpProvider() {
17401
17468
  * // optional method
17402
17469
  * 'response': function(response) {
17403
17470
  * // do something on success
17404
- * return response || $q.when(response);
17471
+ * return response;
17405
17472
  * },
17406
17473
  *
17407
17474
  * // optional method
@@ -17562,7 +17629,7 @@ function $HttpProvider() {
17562
17629
  * caching.
17563
17630
  * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
17564
17631
  * that should abort the request when resolved.
17565
- * - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the
17632
+ * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the
17566
17633
  * XHR object. See [requests with credentials]https://developer.mozilla.org/en/http_access_control#section_5
17567
17634
  * for more information.
17568
17635
  * - **responseType** - `{string}` - see
@@ -17600,11 +17667,11 @@ function $HttpProvider() {
17600
17667
  <button id="samplegetbtn" ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button>
17601
17668
  <button id="samplejsonpbtn"
17602
17669
  ng-click="updateModel('JSONP',
17603
- 'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')">
17670
+ 'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')">
17604
17671
  Sample JSONP
17605
17672
  </button>
17606
17673
  <button id="invalidjsonpbtn"
17607
- ng-click="updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')">
17674
+ ng-click="updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')">
17608
17675
  Invalid JSONP
17609
17676
  </button>
17610
17677
  <pre>http status code: {{status}}</pre>
@@ -17684,14 +17751,6 @@ function $HttpProvider() {
17684
17751
  config.headers = headers;
17685
17752
  config.method = uppercase(config.method);
17686
17753
 
17687
- var xsrfValue = urlIsSameOrigin(config.url)
17688
- ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]
17689
- : undefined;
17690
- if (xsrfValue) {
17691
- headers[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
17692
- }
17693
-
17694
-
17695
17754
  var serverRequest = function(config) {
17696
17755
  headers = config.headers;
17697
17756
  var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);
@@ -17956,7 +18015,7 @@ function $HttpProvider() {
17956
18015
  } else {
17957
18016
  // serving from cache
17958
18017
  if (isArray(cachedResp)) {
17959
- resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]), cachedResp[3]);
18018
+ resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);
17960
18019
  } else {
17961
18020
  resolvePromise(cachedResp, 200, {}, 'OK');
17962
18021
  }
@@ -17967,8 +18026,17 @@ function $HttpProvider() {
17967
18026
  }
17968
18027
  }
17969
18028
 
17970
- // if we won't have the response in cache, send the request to the backend
18029
+
18030
+ // if we won't have the response in cache, set the xsrf headers and
18031
+ // send the request to the backend
17971
18032
  if (isUndefined(cachedResp)) {
18033
+ var xsrfValue = urlIsSameOrigin(config.url)
18034
+ ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]
18035
+ : undefined;
18036
+ if (xsrfValue) {
18037
+ reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
18038
+ }
18039
+
17972
18040
  $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
17973
18041
  config.withCredentials, config.responseType);
17974
18042
  }
@@ -18095,16 +18163,13 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
18095
18163
  var callbackId = '_' + (callbacks.counter++).toString(36);
18096
18164
  callbacks[callbackId] = function(data) {
18097
18165
  callbacks[callbackId].data = data;
18166
+ callbacks[callbackId].called = true;
18098
18167
  };
18099
18168
 
18100
18169
  var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
18101
- function() {
18102
- if (callbacks[callbackId].data) {
18103
- completeRequest(callback, 200, callbacks[callbackId].data);
18104
- } else {
18105
- completeRequest(callback, status || -2);
18106
- }
18107
- callbacks[callbackId] = angular.noop;
18170
+ callbackId, function(status, text) {
18171
+ completeRequest(callback, status, callbacks[callbackId].data, "", text);
18172
+ callbacks[callbackId] = noop;
18108
18173
  });
18109
18174
  } else {
18110
18175
 
@@ -18206,34 +18271,52 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
18206
18271
  }
18207
18272
  };
18208
18273
 
18209
- function jsonpReq(url, done) {
18274
+ function jsonpReq(url, callbackId, done) {
18210
18275
  // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:
18211
18276
  // - fetches local scripts via XHR and evals them
18212
18277
  // - adds and immediately removes script elements from the document
18213
- var script = rawDocument.createElement('script'),
18214
- doneWrapper = function() {
18215
- script.onreadystatechange = script.onload = script.onerror = null;
18216
- rawDocument.body.removeChild(script);
18217
- if (done) done();
18218
- };
18219
-
18220
- script.type = 'text/javascript';
18278
+ var script = rawDocument.createElement('script'), callback = null;
18279
+ script.type = "text/javascript";
18221
18280
  script.src = url;
18281
+ script.async = true;
18282
+
18283
+ callback = function(event) {
18284
+ removeEventListenerFn(script, "load", callback);
18285
+ removeEventListenerFn(script, "error", callback);
18286
+ rawDocument.body.removeChild(script);
18287
+ script = null;
18288
+ var status = -1;
18289
+ var text = "unknown";
18290
+
18291
+ if (event) {
18292
+ if (event.type === "load" && !callbacks[callbackId].called) {
18293
+ event = { type: "error" };
18294
+ }
18295
+ text = event.type;
18296
+ status = event.type === "error" ? 404 : 200;
18297
+ }
18298
+
18299
+ if (done) {
18300
+ done(status, text);
18301
+ }
18302
+ };
18303
+
18304
+ addEventListenerFn(script, "load", callback);
18305
+ addEventListenerFn(script, "error", callback);
18222
18306
 
18223
- if (msie && msie <= 8) {
18307
+ if (msie <= 8) {
18224
18308
  script.onreadystatechange = function() {
18225
- if (/loaded|complete/.test(script.readyState)) {
18226
- doneWrapper();
18309
+ if (isString(script.readyState) && /loaded|complete/.test(script.readyState)) {
18310
+ script.onreadystatechange = null;
18311
+ callback({
18312
+ type: 'load'
18313
+ });
18227
18314
  }
18228
18315
  };
18229
- } else {
18230
- script.onload = script.onerror = function() {
18231
- doneWrapper();
18232
- };
18233
18316
  }
18234
18317
 
18235
18318
  rawDocument.body.appendChild(script);
18236
- return doneWrapper;
18319
+ return callback;
18237
18320
  }
18238
18321
  }
18239
18322
 
@@ -18242,7 +18325,7 @@ var $interpolateMinErr = minErr('$interpolate');
18242
18325
  /**
18243
18326
  * @ngdoc provider
18244
18327
  * @name $interpolateProvider
18245
- * @function
18328
+ * @kind function
18246
18329
  *
18247
18330
  * @description
18248
18331
  *
@@ -18260,7 +18343,7 @@ var $interpolateMinErr = minErr('$interpolate');
18260
18343
  });
18261
18344
 
18262
18345
 
18263
- customInterpolationApp.controller('DemoController', function DemoController() {
18346
+ customInterpolationApp.controller('DemoController', function() {
18264
18347
  this.label = "This binding is brought you by // interpolation symbols.";
18265
18348
  });
18266
18349
  </script>
@@ -18323,7 +18406,7 @@ function $InterpolateProvider() {
18323
18406
  /**
18324
18407
  * @ngdoc service
18325
18408
  * @name $interpolate
18326
- * @function
18409
+ * @kind function
18327
18410
  *
18328
18411
  * @requires $parse
18329
18412
  * @requires $sce
@@ -18415,10 +18498,24 @@ function $InterpolateProvider() {
18415
18498
  } else {
18416
18499
  part = $sce.valueOf(part);
18417
18500
  }
18418
- if (part === null || isUndefined(part)) {
18501
+ if (part == null) { // null || undefined
18419
18502
  part = '';
18420
- } else if (typeof part != 'string') {
18421
- part = toJson(part);
18503
+ } else {
18504
+ switch (typeof part) {
18505
+ case 'string':
18506
+ {
18507
+ break;
18508
+ }
18509
+ case 'number':
18510
+ {
18511
+ part = '' + part;
18512
+ break;
18513
+ }
18514
+ default:
18515
+ {
18516
+ part = toJson(part);
18517
+ }
18518
+ }
18422
18519
  }
18423
18520
  }
18424
18521
  concat[i] = part;
@@ -18929,7 +19026,7 @@ function LocationHashbangUrl(appBase, hashPrefix) {
18929
19026
  Matches paths for file protocol on windows,
18930
19027
  such as /C:/foo/bar, and captures only /foo/bar.
18931
19028
  */
18932
- var windowsFilePathExp = /^\/?.*?:(\/.*)/;
19029
+ var windowsFilePathExp = /^\/[A-Z]:(\/.*)/;
18933
19030
 
18934
19031
  var firstPathSegmentMatch;
18935
19032
 
@@ -18938,10 +19035,7 @@ function LocationHashbangUrl(appBase, hashPrefix) {
18938
19035
  url = url.replace(base, '');
18939
19036
  }
18940
19037
 
18941
- /*
18942
- * The input URL intentionally contains a
18943
- * first path segment that ends with a colon.
18944
- */
19038
+ // The input URL intentionally contains a first path segment that ends with a colon.
18945
19039
  if (windowsFilePathExp.exec(url)) {
18946
19040
  return path;
18947
19041
  }
@@ -18997,6 +19091,16 @@ function LocationHashbangInHtml5Url(appBase, hashPrefix) {
18997
19091
  return appBaseNoFile;
18998
19092
  }
18999
19093
  };
19094
+
19095
+ this.$$compose = function() {
19096
+ var search = toKeyValue(this.$$search),
19097
+ hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
19098
+
19099
+ this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
19100
+ // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#'
19101
+ this.$$absUrl = appBase + hashPrefix + this.$$url;
19102
+ };
19103
+
19000
19104
  }
19001
19105
 
19002
19106
 
@@ -19128,15 +19232,37 @@ LocationHashbangInHtml5Url.prototype =
19128
19232
  *
19129
19233
  * Change search part when called with parameter and return `$location`.
19130
19234
  *
19235
+ *
19236
+ * ```js
19237
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
19238
+ * var searchObject = $location.search();
19239
+ * // => {foo: 'bar', baz: 'xoxo'}
19240
+ *
19241
+ *
19242
+ * // set foo to 'yipee'
19243
+ * $location.search('foo', 'yipee');
19244
+ * // => $location
19245
+ * ```
19246
+ *
19131
19247
  * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or
19132
- * hash object. Hash object may contain an array of values, which will be decoded as duplicates in
19133
- * the url.
19248
+ * hash object.
19249
+ *
19250
+ * When called with a single argument the method acts as a setter, setting the `search` component
19251
+ * of `$location` to the specified value.
19252
+ *
19253
+ * If the argument is a hash object containing an array of values, these values will be encoded
19254
+ * as duplicate search parameters in the url.
19134
19255
  *
19135
- * @param {(string|Array<string>)=} paramValue If `search` is a string, then `paramValue` will override only a
19136
- * single search parameter. If `paramValue` is an array, it will set the parameter as a
19137
- * comma-separated value. If `paramValue` is `null`, the parameter will be deleted.
19256
+ * @param {(string|Array<string>)=} paramValue If `search` is a string, then `paramValue` will
19257
+ * override only a single search property.
19138
19258
  *
19139
- * @return {string} search
19259
+ * If `paramValue` is an array, it will override the property of the `search` component of
19260
+ * `$location` specified via the first argument.
19261
+ *
19262
+ * If `paramValue` is `null`, the property specified via the first argument will be deleted.
19263
+ *
19264
+ * @return {Object} If called with no arguments returns the parsed `search` object. If called with
19265
+ * one or more arguments returns `$location` object itself.
19140
19266
  */
19141
19267
  search: function(search, paramValue) {
19142
19268
  switch (arguments.length) {
@@ -19349,6 +19475,39 @@ function $LocationProvider(){
19349
19475
  absHref = urlResolve(absHref.animVal).href;
19350
19476
  }
19351
19477
 
19478
+ // Make relative links work in HTML5 mode for legacy browsers (or at least IE8 & 9)
19479
+ // The href should be a regular url e.g. /link/somewhere or link/somewhere or ../somewhere or
19480
+ // somewhere#anchor or http://example.com/somewhere
19481
+ if (LocationMode === LocationHashbangInHtml5Url) {
19482
+ // get the actual href attribute - see
19483
+ // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx
19484
+ var href = elm.attr('href') || elm.attr('xlink:href');
19485
+
19486
+ if (href.indexOf('://') < 0) { // Ignore absolute URLs
19487
+ var prefix = '#' + hashPrefix;
19488
+ if (href[0] == '/') {
19489
+ // absolute path - replace old path
19490
+ absHref = appBase + prefix + href;
19491
+ } else if (href[0] == '#') {
19492
+ // local anchor
19493
+ absHref = appBase + prefix + ($location.path() || '/') + href;
19494
+ } else {
19495
+ // relative path - join with current path
19496
+ var stack = $location.path().split("/"),
19497
+ parts = href.split("/");
19498
+ for (var i=0; i<parts.length; i++) {
19499
+ if (parts[i] == ".")
19500
+ continue;
19501
+ else if (parts[i] == "..")
19502
+ stack.pop();
19503
+ else if (parts[i].length)
19504
+ stack.push(parts[i]);
19505
+ }
19506
+ absHref = appBase + prefix + stack.join('/');
19507
+ }
19508
+ }
19509
+ }
19510
+
19352
19511
  var rewrittenUrl = $location.$$rewrite(absHref);
19353
19512
 
19354
19513
  if (absHref && !elm.attr('target') && rewrittenUrl && !event.isDefaultPrevented()) {
@@ -19709,9 +19868,6 @@ Lexer.prototype = {
19709
19868
 
19710
19869
  this.tokens = [];
19711
19870
 
19712
- var token;
19713
- var json = [];
19714
-
19715
19871
  while (this.index < this.text.length) {
19716
19872
  this.ch = this.text.charAt(this.index);
19717
19873
  if (this.is('"\'')) {
@@ -19720,19 +19876,11 @@ Lexer.prototype = {
19720
19876
  this.readNumber();
19721
19877
  } else if (this.isIdent(this.ch)) {
19722
19878
  this.readIdent();
19723
- // identifiers can only be if the preceding char was a { or ,
19724
- if (this.was('{,') && json[0] === '{' &&
19725
- (token = this.tokens[this.tokens.length - 1])) {
19726
- token.json = token.text.indexOf('.') === -1;
19727
- }
19728
19879
  } else if (this.is('(){}[].,;:?')) {
19729
19880
  this.tokens.push({
19730
19881
  index: this.index,
19731
- text: this.ch,
19732
- json: (this.was(':[,') && this.is('{[')) || this.is('}]:,')
19882
+ text: this.ch
19733
19883
  });
19734
- if (this.is('{[')) json.unshift(this.ch);
19735
- if (this.is('}]')) json.shift();
19736
19884
  this.index++;
19737
19885
  } else if (this.isWhitespace(this.ch)) {
19738
19886
  this.index++;
@@ -19753,8 +19901,7 @@ Lexer.prototype = {
19753
19901
  this.tokens.push({
19754
19902
  index: this.index,
19755
19903
  text: this.ch,
19756
- fn: fn,
19757
- json: (this.was('[,:') && this.is('+-'))
19904
+ fn: fn
19758
19905
  });
19759
19906
  this.index += 1;
19760
19907
  } else {
@@ -19837,7 +19984,8 @@ Lexer.prototype = {
19837
19984
  this.tokens.push({
19838
19985
  index: start,
19839
19986
  text: number,
19840
- json: true,
19987
+ literal: true,
19988
+ constant: true,
19841
19989
  fn: function() { return number; }
19842
19990
  });
19843
19991
  },
@@ -19889,7 +20037,8 @@ Lexer.prototype = {
19889
20037
  // OPERATORS is our own object so we don't need to use special hasOwnPropertyFn
19890
20038
  if (OPERATORS.hasOwnProperty(ident)) {
19891
20039
  token.fn = OPERATORS[ident];
19892
- token.json = OPERATORS[ident];
20040
+ token.literal = true;
20041
+ token.constant = true;
19893
20042
  } else {
19894
20043
  var getter = getterFn(ident, this.options, this.text);
19895
20044
  token.fn = extend(function(self, locals) {
@@ -19906,13 +20055,11 @@ Lexer.prototype = {
19906
20055
  if (methodName) {
19907
20056
  this.tokens.push({
19908
20057
  index:lastDot,
19909
- text: '.',
19910
- json: false
20058
+ text: '.'
19911
20059
  });
19912
20060
  this.tokens.push({
19913
20061
  index: lastDot + 1,
19914
- text: methodName,
19915
- json: false
20062
+ text: methodName
19916
20063
  });
19917
20064
  }
19918
20065
  },
@@ -19950,7 +20097,8 @@ Lexer.prototype = {
19950
20097
  index: start,
19951
20098
  text: rawString,
19952
20099
  string: string,
19953
- json: true,
20100
+ literal: true,
20101
+ constant: true,
19954
20102
  fn: function() { return string; }
19955
20103
  });
19956
20104
  return;
@@ -19982,28 +20130,12 @@ Parser.ZERO = extend(function () {
19982
20130
  Parser.prototype = {
19983
20131
  constructor: Parser,
19984
20132
 
19985
- parse: function (text, json) {
20133
+ parse: function (text) {
19986
20134
  this.text = text;
19987
20135
 
19988
- //TODO(i): strip all the obsolte json stuff from this file
19989
- this.json = json;
19990
-
19991
20136
  this.tokens = this.lexer.lex(text);
19992
20137
 
19993
- if (json) {
19994
- // The extra level of aliasing is here, just in case the lexer misses something, so that
19995
- // we prevent any accidental execution in JSON.
19996
- this.assignment = this.logicalOR;
19997
-
19998
- this.functionCall =
19999
- this.fieldAccess =
20000
- this.objectIndex =
20001
- this.filterChain = function() {
20002
- this.throwError('is not valid json', {text: text, index: 0});
20003
- };
20004
- }
20005
-
20006
- var value = json ? this.primary() : this.statements();
20138
+ var value = this.statements();
20007
20139
 
20008
20140
  if (this.tokens.length !== 0) {
20009
20141
  this.throwError('is an unexpected token', this.tokens[0]);
@@ -20030,10 +20162,8 @@ Parser.prototype = {
20030
20162
  if (!primary) {
20031
20163
  this.throwError('not a primary expression', token);
20032
20164
  }
20033
- if (token.json) {
20034
- primary.constant = true;
20035
- primary.literal = true;
20036
- }
20165
+ primary.literal = !!token.literal;
20166
+ primary.constant = !!token.constant;
20037
20167
  }
20038
20168
 
20039
20169
  var next, context;
@@ -20081,9 +20211,6 @@ Parser.prototype = {
20081
20211
  expect: function(e1, e2, e3, e4){
20082
20212
  var token = this.peek(e1, e2, e3, e4);
20083
20213
  if (token) {
20084
- if (this.json && !token.json) {
20085
- this.throwError('is not valid json', token);
20086
- }
20087
20214
  this.tokens.shift();
20088
20215
  return token;
20089
20216
  }
@@ -20718,7 +20845,7 @@ function getterFn(path, options, fullExp) {
20718
20845
  /**
20719
20846
  * @ngdoc provider
20720
20847
  * @name $parseProvider
20721
- * @function
20848
+ * @kind function
20722
20849
  *
20723
20850
  * @description
20724
20851
  * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
@@ -20837,7 +20964,7 @@ function $ParseProvider() {
20837
20964
 
20838
20965
  var lexer = new Lexer($parseOptions);
20839
20966
  var parser = new Parser(lexer, $filter, $parseOptions);
20840
- parsedExpression = parser.parse(exp, false);
20967
+ parsedExpression = parser.parse(exp);
20841
20968
 
20842
20969
  if (exp !== 'hasOwnProperty') {
20843
20970
  // Only cache the value if it's not going to mess up the cache object
@@ -21048,7 +21175,7 @@ function qFactory(nextTick, exceptionHandler) {
21048
21175
  /**
21049
21176
  * @ngdoc method
21050
21177
  * @name $q#defer
21051
- * @function
21178
+ * @kind function
21052
21179
  *
21053
21180
  * @description
21054
21181
  * Creates a `Deferred` object which represents a task which will finish in the future.
@@ -21205,7 +21332,7 @@ function qFactory(nextTick, exceptionHandler) {
21205
21332
  /**
21206
21333
  * @ngdoc method
21207
21334
  * @name $q#reject
21208
- * @function
21335
+ * @kind function
21209
21336
  *
21210
21337
  * @description
21211
21338
  * Creates a promise that is resolved as rejected with the specified `reason`. This api should be
@@ -21265,7 +21392,7 @@ function qFactory(nextTick, exceptionHandler) {
21265
21392
  /**
21266
21393
  * @ngdoc method
21267
21394
  * @name $q#when
21268
- * @function
21395
+ * @kind function
21269
21396
  *
21270
21397
  * @description
21271
21398
  * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
@@ -21337,7 +21464,7 @@ function qFactory(nextTick, exceptionHandler) {
21337
21464
  /**
21338
21465
  * @ngdoc method
21339
21466
  * @name $q#all
21340
- * @function
21467
+ * @kind function
21341
21468
  *
21342
21469
  * @description
21343
21470
  * Combines multiple promises into a single promise that is resolved when all of the input
@@ -21428,7 +21555,7 @@ function $$RAFProvider(){ //rAF
21428
21555
  *
21429
21556
  * Loop operations are optimized by using while(count--) { ... }
21430
21557
  * - this means that in order to keep the same order of execution as addition we have to add
21431
- * items to the array at the beginning (shift) instead of at the end (push)
21558
+ * items to the array at the beginning (unshift) instead of at the end (push)
21432
21559
  *
21433
21560
  * Child scopes are created and removed often
21434
21561
  * - Using an array would be slow since inserts in middle are expensive so we use linked list
@@ -21562,7 +21689,7 @@ function $RootScopeProvider(){
21562
21689
  /**
21563
21690
  * @ngdoc method
21564
21691
  * @name $rootScope.Scope#$new
21565
- * @function
21692
+ * @kind function
21566
21693
  *
21567
21694
  * @description
21568
21695
  * Creates a new child {@link ng.$rootScope.Scope scope}.
@@ -21594,18 +21721,23 @@ function $RootScopeProvider(){
21594
21721
  child.$$asyncQueue = this.$$asyncQueue;
21595
21722
  child.$$postDigestQueue = this.$$postDigestQueue;
21596
21723
  } else {
21597
- ChildScope = function() {}; // should be anonymous; This is so that when the minifier munges
21598
- // the name it does not become random set of chars. This will then show up as class
21599
- // name in the web inspector.
21600
- ChildScope.prototype = this;
21601
- child = new ChildScope();
21602
- child.$id = nextUid();
21724
+ // Only create a child scope class if somebody asks for one,
21725
+ // but cache it to allow the VM to optimize lookups.
21726
+ if (!this.$$childScopeClass) {
21727
+ this.$$childScopeClass = function() {
21728
+ this.$$watchers = this.$$nextSibling =
21729
+ this.$$childHead = this.$$childTail = null;
21730
+ this.$$listeners = {};
21731
+ this.$$listenerCount = {};
21732
+ this.$id = nextUid();
21733
+ this.$$childScopeClass = null;
21734
+ };
21735
+ this.$$childScopeClass.prototype = this;
21736
+ }
21737
+ child = new this.$$childScopeClass();
21603
21738
  }
21604
21739
  child['this'] = child;
21605
- child.$$listeners = {};
21606
- child.$$listenerCount = {};
21607
21740
  child.$parent = this;
21608
- child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;
21609
21741
  child.$$prevSibling = this.$$childTail;
21610
21742
  if (this.$$childHead) {
21611
21743
  this.$$childTail.$$nextSibling = child;
@@ -21619,7 +21751,7 @@ function $RootScopeProvider(){
21619
21751
  /**
21620
21752
  * @ngdoc method
21621
21753
  * @name $rootScope.Scope#$watch
21622
- * @function
21754
+ * @kind function
21623
21755
  *
21624
21756
  * @description
21625
21757
  * Registers a `listener` callback to be executed whenever the `watchExpression` changes.
@@ -21631,10 +21763,14 @@ function $RootScopeProvider(){
21631
21763
  * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)
21632
21764
  * - The `listener` is called only when the value from the current `watchExpression` and the
21633
21765
  * previous call to `watchExpression` are not equal (with the exception of the initial run,
21634
- * see below). The inequality is determined according to
21635
- * {@link angular.equals} function. To save the value of the object for later comparison,
21636
- * the {@link angular.copy} function is used. It also means that watching complex options
21637
- * will have adverse memory and performance implications.
21766
+ * see below). Inequality is determined according to reference inequality,
21767
+ * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)
21768
+ * via the `!==` Javascript operator, unless `objectEquality == true`
21769
+ * (see next point)
21770
+ * - When `objectEquality == true`, inequality of the `watchExpression` is determined
21771
+ * according to the {@link angular.equals} function. To save the value of the object for
21772
+ * later comparison, the {@link angular.copy} function is used. This therefore means that
21773
+ * watching complex objects will have adverse memory and performance implications.
21638
21774
  * - The watch `listener` may change the model, which may trigger other `listener`s to fire.
21639
21775
  * This is achieved by rerunning the watchers until no changes are detected. The rerun
21640
21776
  * iteration limit is 10 to prevent an infinite loop deadlock.
@@ -21669,13 +21805,17 @@ function $RootScopeProvider(){
21669
21805
  expect(scope.counter).toEqual(0);
21670
21806
 
21671
21807
  scope.$digest();
21672
- // no variable change
21673
- expect(scope.counter).toEqual(0);
21808
+ // the listener is always called during the first $digest loop after it was registered
21809
+ expect(scope.counter).toEqual(1);
21674
21810
 
21675
- scope.name = 'adam';
21676
21811
  scope.$digest();
21812
+ // but now it will not be called unless the value changes
21677
21813
  expect(scope.counter).toEqual(1);
21678
21814
 
21815
+ scope.name = 'adam';
21816
+ scope.$digest();
21817
+ expect(scope.counter).toEqual(2);
21818
+
21679
21819
 
21680
21820
 
21681
21821
  // Using a listener function
@@ -21761,7 +21901,7 @@ function $RootScopeProvider(){
21761
21901
  // the while loop reads in reverse order.
21762
21902
  array.unshift(watcher);
21763
21903
 
21764
- return function() {
21904
+ return function deregisterWatch() {
21765
21905
  arrayRemove(array, watcher);
21766
21906
  lastDirtyWatch = null;
21767
21907
  };
@@ -21771,7 +21911,7 @@ function $RootScopeProvider(){
21771
21911
  /**
21772
21912
  * @ngdoc method
21773
21913
  * @name $rootScope.Scope#$watchCollection
21774
- * @function
21914
+ * @kind function
21775
21915
  *
21776
21916
  * @description
21777
21917
  * Shallow watches the properties of an object and fires whenever any of the properties change
@@ -21947,7 +22087,7 @@ function $RootScopeProvider(){
21947
22087
  /**
21948
22088
  * @ngdoc method
21949
22089
  * @name $rootScope.Scope#$digest
21950
- * @function
22090
+ * @kind function
21951
22091
  *
21952
22092
  * @description
21953
22093
  * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and
@@ -21982,12 +22122,16 @@ function $RootScopeProvider(){
21982
22122
  expect(scope.counter).toEqual(0);
21983
22123
 
21984
22124
  scope.$digest();
21985
- // no variable change
21986
- expect(scope.counter).toEqual(0);
22125
+ // the listener is always called during the first $digest loop after it was registered
22126
+ expect(scope.counter).toEqual(1);
21987
22127
 
21988
- scope.name = 'adam';
21989
22128
  scope.$digest();
22129
+ // but now it will not be called unless the value changes
21990
22130
  expect(scope.counter).toEqual(1);
22131
+
22132
+ scope.name = 'adam';
22133
+ scope.$digest();
22134
+ expect(scope.counter).toEqual(2);
21991
22135
  * ```
21992
22136
  *
21993
22137
  */
@@ -22039,7 +22183,7 @@ function $RootScopeProvider(){
22039
22183
  && isNaN(value) && isNaN(last)))) {
22040
22184
  dirty = true;
22041
22185
  lastDirtyWatch = watch;
22042
- watch.last = watch.eq ? copy(value) : value;
22186
+ watch.last = watch.eq ? copy(value, null) : value;
22043
22187
  watch.fn(value, ((last === initWatchVal) ? value : last), current);
22044
22188
  if (ttl < 5) {
22045
22189
  logIdx = 4 - ttl;
@@ -22114,7 +22258,7 @@ function $RootScopeProvider(){
22114
22258
  /**
22115
22259
  * @ngdoc method
22116
22260
  * @name $rootScope.Scope#$destroy
22117
- * @function
22261
+ * @kind function
22118
22262
  *
22119
22263
  * @description
22120
22264
  * Removes the current scope (and all of its children) from the parent scope. Removal implies
@@ -22175,7 +22319,7 @@ function $RootScopeProvider(){
22175
22319
  /**
22176
22320
  * @ngdoc method
22177
22321
  * @name $rootScope.Scope#$eval
22178
- * @function
22322
+ * @kind function
22179
22323
  *
22180
22324
  * @description
22181
22325
  * Executes the `expression` on the current scope and returns the result. Any exceptions in
@@ -22207,7 +22351,7 @@ function $RootScopeProvider(){
22207
22351
  /**
22208
22352
  * @ngdoc method
22209
22353
  * @name $rootScope.Scope#$evalAsync
22210
- * @function
22354
+ * @kind function
22211
22355
  *
22212
22356
  * @description
22213
22357
  * Executes the expression on the current scope at a later point in time.
@@ -22254,7 +22398,7 @@ function $RootScopeProvider(){
22254
22398
  /**
22255
22399
  * @ngdoc method
22256
22400
  * @name $rootScope.Scope#$apply
22257
- * @function
22401
+ * @kind function
22258
22402
  *
22259
22403
  * @description
22260
22404
  * `$apply()` is used to execute an expression in angular from outside of the angular
@@ -22316,7 +22460,7 @@ function $RootScopeProvider(){
22316
22460
  /**
22317
22461
  * @ngdoc method
22318
22462
  * @name $rootScope.Scope#$on
22319
- * @function
22463
+ * @kind function
22320
22464
  *
22321
22465
  * @description
22322
22466
  * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for
@@ -22365,7 +22509,7 @@ function $RootScopeProvider(){
22365
22509
  /**
22366
22510
  * @ngdoc method
22367
22511
  * @name $rootScope.Scope#$emit
22368
- * @function
22512
+ * @kind function
22369
22513
  *
22370
22514
  * @description
22371
22515
  * Dispatches an event `name` upwards through the scope hierarchy notifying the
@@ -22433,7 +22577,7 @@ function $RootScopeProvider(){
22433
22577
  /**
22434
22578
  * @ngdoc method
22435
22579
  * @name $rootScope.Scope#$broadcast
22436
- * @function
22580
+ * @kind function
22437
22581
  *
22438
22582
  * @description
22439
22583
  * Dispatches an event `name` downwards to all child scopes (and their children) notifying the
@@ -22681,7 +22825,7 @@ function adjustMatchers(matchers) {
22681
22825
  /**
22682
22826
  * @ngdoc service
22683
22827
  * @name $sceDelegate
22684
- * @function
22828
+ * @kind function
22685
22829
  *
22686
22830
  * @description
22687
22831
  *
@@ -22753,7 +22897,7 @@ function $SceDelegateProvider() {
22753
22897
  /**
22754
22898
  * @ngdoc method
22755
22899
  * @name $sceDelegateProvider#resourceUrlWhitelist
22756
- * @function
22900
+ * @kind function
22757
22901
  *
22758
22902
  * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
22759
22903
  * provided. This must be an array or null. A snapshot of this array is used so further
@@ -22782,7 +22926,7 @@ function $SceDelegateProvider() {
22782
22926
  /**
22783
22927
  * @ngdoc method
22784
22928
  * @name $sceDelegateProvider#resourceUrlBlacklist
22785
- * @function
22929
+ * @kind function
22786
22930
  *
22787
22931
  * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
22788
22932
  * provided. This must be an array or null. A snapshot of this array is used so further
@@ -23009,7 +23153,7 @@ function $SceDelegateProvider() {
23009
23153
  /**
23010
23154
  * @ngdoc service
23011
23155
  * @name $sce
23012
- * @function
23156
+ * @kind function
23013
23157
  *
23014
23158
  * @description
23015
23159
  *
@@ -23135,7 +23279,7 @@ function $SceDelegateProvider() {
23135
23279
  *
23136
23280
  * | Context | Notes |
23137
23281
  * |---------------------|----------------|
23138
- * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. |
23282
+ * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |
23139
23283
  * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |
23140
23284
  * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |
23141
23285
  * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
@@ -23159,7 +23303,7 @@ function $SceDelegateProvider() {
23159
23303
  * - `**`: matches zero or more occurrences of *any* character. As such, it's not
23160
23304
  * not appropriate to use in for a scheme, domain, etc. as it would match too much. (e.g.
23161
23305
  * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might
23162
- * not have been the intention.) It's usage at the very end of the path is ok. (e.g.
23306
+ * not have been the intention.) Its usage at the very end of the path is ok. (e.g.
23163
23307
  * http://foo.example.com/templates/**).
23164
23308
  * - **RegExp** (*see caveat below*)
23165
23309
  * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax
@@ -23280,7 +23424,7 @@ function $SceProvider() {
23280
23424
  /**
23281
23425
  * @ngdoc method
23282
23426
  * @name $sceProvider#enabled
23283
- * @function
23427
+ * @kind function
23284
23428
  *
23285
23429
  * @param {boolean=} value If provided, then enables/disables SCE.
23286
23430
  * @return {boolean} true if SCE is enabled, false otherwise.
@@ -23353,12 +23497,12 @@ function $SceProvider() {
23353
23497
  'document. See http://docs.angularjs.org/api/ng.$sce for more information.');
23354
23498
  }
23355
23499
 
23356
- var sce = copy(SCE_CONTEXTS);
23500
+ var sce = shallowCopy(SCE_CONTEXTS);
23357
23501
 
23358
23502
  /**
23359
23503
  * @ngdoc method
23360
23504
  * @name $sce#isEnabled
23361
- * @function
23505
+ * @kind function
23362
23506
  *
23363
23507
  * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you
23364
23508
  * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
@@ -23893,7 +24037,7 @@ var originUrl = urlResolve(window.location.href, true);
23893
24037
  * https://github.com/angular/angular.js/pull/2902
23894
24038
  * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
23895
24039
  *
23896
- * @function
24040
+ * @kind function
23897
24041
  * @param {string} url The URL to be parsed.
23898
24042
  * @description Normalizes and parses a URL.
23899
24043
  * @returns {object} Returns the normalized URL as a dictionary.
@@ -24057,7 +24201,7 @@ function $WindowProvider(){
24057
24201
  /**
24058
24202
  * @ngdoc service
24059
24203
  * @name $filter
24060
- * @function
24204
+ * @kind function
24061
24205
  * @description
24062
24206
  * Filters are used for formatting data displayed to the user.
24063
24207
  *
@@ -24067,7 +24211,24 @@ function $WindowProvider(){
24067
24211
  *
24068
24212
  * @param {String} name Name of the filter function to retrieve
24069
24213
  * @return {Function} the filter function
24070
- */
24214
+ * @example
24215
+ <example name="$filter" module="filterExample">
24216
+ <file name="index.html">
24217
+ <div ng-controller="MainCtrl">
24218
+ <h3>{{ originalText }}</h3>
24219
+ <h3>{{ filteredText }}</h3>
24220
+ </div>
24221
+ </file>
24222
+
24223
+ <file name="script.js">
24224
+ angular.module('filterExample', [])
24225
+ .controller('MainCtrl', function($scope, $filter) {
24226
+ $scope.originalText = 'hello';
24227
+ $scope.filteredText = $filter('uppercase')($scope.originalText);
24228
+ });
24229
+ </file>
24230
+ </example>
24231
+ */
24071
24232
  $FilterProvider.$inject = ['$provide'];
24072
24233
  function $FilterProvider($provide) {
24073
24234
  var suffix = 'Filter';
@@ -24127,7 +24288,7 @@ function $FilterProvider($provide) {
24127
24288
  /**
24128
24289
  * @ngdoc filter
24129
24290
  * @name filter
24130
- * @function
24291
+ * @kind function
24131
24292
  *
24132
24293
  * @description
24133
24294
  * Selects a subset of items from `array` and returns it as a new array.
@@ -24159,15 +24320,15 @@ function $FilterProvider($provide) {
24159
24320
  *
24160
24321
  * Can be one of:
24161
24322
  *
24162
- * - `function(actual, expected)`:
24163
- * The function will be given the object value and the predicate value to compare and
24164
- * should return true if the item should be included in filtered result.
24323
+ * - `function(actual, expected)`:
24324
+ * The function will be given the object value and the predicate value to compare and
24325
+ * should return true if the item should be included in filtered result.
24165
24326
  *
24166
- * - `true`: A shorthand for `function(actual, expected) { return angular.equals(expected, actual)}`.
24167
- * this is essentially strict comparison of expected and actual.
24327
+ * - `true`: A shorthand for `function(actual, expected) { return angular.equals(expected, actual)}`.
24328
+ * this is essentially strict comparison of expected and actual.
24168
24329
  *
24169
- * - `false|undefined`: A short hand for a function which will look for a substring match in case
24170
- * insensitive way.
24330
+ * - `false|undefined`: A short hand for a function which will look for a substring match in case
24331
+ * insensitive way.
24171
24332
  *
24172
24333
  * @example
24173
24334
  <example>
@@ -24346,7 +24507,7 @@ function filterFilter() {
24346
24507
  /**
24347
24508
  * @ngdoc filter
24348
24509
  * @name currency
24349
- * @function
24510
+ * @kind function
24350
24511
  *
24351
24512
  * @description
24352
24513
  * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default
@@ -24403,7 +24564,7 @@ function currencyFilter($locale) {
24403
24564
  /**
24404
24565
  * @ngdoc filter
24405
24566
  * @name number
24406
- * @function
24567
+ * @kind function
24407
24568
  *
24408
24569
  * @description
24409
24570
  * Formats a number as text.
@@ -24488,8 +24649,8 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
24488
24649
  fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
24489
24650
  }
24490
24651
 
24491
- var pow = Math.pow(10, fractionSize);
24492
- number = Math.round(number * pow) / pow;
24652
+ var pow = Math.pow(10, fractionSize + 1);
24653
+ number = Math.floor(number * pow + 5) / pow;
24493
24654
  var fraction = ('' + number).split(DECIMAL_SEP);
24494
24655
  var whole = fraction[0];
24495
24656
  fraction = fraction[1] || '';
@@ -24615,7 +24776,7 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
24615
24776
  /**
24616
24777
  * @ngdoc filter
24617
24778
  * @name date
24618
- * @function
24779
+ * @kind function
24619
24780
  *
24620
24781
  * @description
24621
24782
  * Formats `date` to a string based on the requested `format`.
@@ -24772,7 +24933,7 @@ function dateFilter($locale) {
24772
24933
  /**
24773
24934
  * @ngdoc filter
24774
24935
  * @name json
24775
- * @function
24936
+ * @kind function
24776
24937
  *
24777
24938
  * @description
24778
24939
  * Allows you to convert a JavaScript object into JSON string.
@@ -24807,7 +24968,7 @@ function jsonFilter() {
24807
24968
  /**
24808
24969
  * @ngdoc filter
24809
24970
  * @name lowercase
24810
- * @function
24971
+ * @kind function
24811
24972
  * @description
24812
24973
  * Converts string to lowercase.
24813
24974
  * @see angular.lowercase
@@ -24818,7 +24979,7 @@ var lowercaseFilter = valueFn(lowercase);
24818
24979
  /**
24819
24980
  * @ngdoc filter
24820
24981
  * @name uppercase
24821
- * @function
24982
+ * @kind function
24822
24983
  * @description
24823
24984
  * Converts string to uppercase.
24824
24985
  * @see angular.uppercase
@@ -24828,7 +24989,7 @@ var uppercaseFilter = valueFn(uppercase);
24828
24989
  /**
24829
24990
  * @ngdoc filter
24830
24991
  * @name limitTo
24831
- * @function
24992
+ * @kind function
24832
24993
  *
24833
24994
  * @description
24834
24995
  * Creates a new array or string containing only a specified number of elements. The elements
@@ -24898,7 +25059,11 @@ function limitToFilter(){
24898
25059
  return function(input, limit) {
24899
25060
  if (!isArray(input) && !isString(input)) return input;
24900
25061
 
24901
- limit = int(limit);
25062
+ if (Math.abs(Number(limit)) === Infinity) {
25063
+ limit = Number(limit);
25064
+ } else {
25065
+ limit = int(limit);
25066
+ }
24902
25067
 
24903
25068
  if (isString(input)) {
24904
25069
  //NaN check on limit
@@ -24937,10 +25102,12 @@ function limitToFilter(){
24937
25102
  /**
24938
25103
  * @ngdoc filter
24939
25104
  * @name orderBy
24940
- * @function
25105
+ * @kind function
24941
25106
  *
24942
25107
  * @description
24943
- * Orders a specified `array` by the `expression` predicate.
25108
+ * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
25109
+ * for strings and numerically for numbers. Note: if you notice numbers are not being sorted
25110
+ * correctly, make sure they are actually being saved as numbers and not strings.
24944
25111
  *
24945
25112
  * @param {Array} array The array to sort.
24946
25113
  * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be
@@ -24993,6 +25160,51 @@ function limitToFilter(){
24993
25160
  </div>
24994
25161
  </file>
24995
25162
  </example>
25163
+ *
25164
+ * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
25165
+ * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the
25166
+ * desired parameters.
25167
+ *
25168
+ * Example:
25169
+ *
25170
+ * @example
25171
+ <example>
25172
+ <file name="index.html">
25173
+ <div ng-controller="Ctrl">
25174
+ <table class="friend">
25175
+ <tr>
25176
+ <th><a href="" ng-click="reverse=false;order('name', false)">Name</a>
25177
+ (<a href="" ng-click="order('-name',false)">^</a>)</th>
25178
+ <th><a href="" ng-click="reverse=!reverse;order('phone', reverse)">Phone Number</a></th>
25179
+ <th><a href="" ng-click="reverse=!reverse;order('age',reverse)">Age</a></th>
25180
+ </tr>
25181
+ <tr ng-repeat="friend in friends">
25182
+ <td>{{friend.name}}</td>
25183
+ <td>{{friend.phone}}</td>
25184
+ <td>{{friend.age}}</td>
25185
+ </tr>
25186
+ </table>
25187
+ </div>
25188
+ </file>
25189
+
25190
+ <file name="script.js">
25191
+ function Ctrl($scope, $filter) {
25192
+ var orderBy = $filter('orderBy');
25193
+ $scope.friends = [
25194
+ { name: 'John', phone: '555-1212', age: 10 },
25195
+ { name: 'Mary', phone: '555-9876', age: 19 },
25196
+ { name: 'Mike', phone: '555-4321', age: 21 },
25197
+ { name: 'Adam', phone: '555-5678', age: 35 },
25198
+ { name: 'Julie', phone: '555-8765', age: 29 }
25199
+ ];
25200
+
25201
+ $scope.order = function(predicate, reverse) {
25202
+ $scope.friends = orderBy($scope.friends, predicate, reverse);
25203
+ };
25204
+ $scope.order('-age',false);
25205
+ }
25206
+ </file>
25207
+ </example>
24996
25208
  */
24997
25209
  orderByFilter.$inject = ['$parse'];
24998
25210
  function orderByFilter($parse){
@@ -25544,7 +25756,7 @@ var nullFormCtrl = {
25544
25756
  * - `url`
25545
25757
  *
25546
25758
  * @description
25547
- * `FormController` keeps track of all its controls and nested forms as well as state of them,
25759
+ * `FormController` keeps track of all its controls and nested forms as well as the state of them,
25548
25760
  * such as being valid/invalid or dirty/pristine.
25549
25761
  *
25550
25762
  * Each {@link ng.directive:form form} directive creates an instance
@@ -26386,6 +26598,8 @@ function addNativeHtml5Validators(ctrl, validatorName, element) {
26386
26598
 
26387
26599
  function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
26388
26600
  var validity = element.prop('validity');
26601
+ var placeholder = element[0].placeholder, noevent = {};
26602
+
26389
26603
  // In composition mode, users are still inputing intermediate text buffer,
26390
26604
  // hold the listener until composition is done.
26391
26605
  // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
@@ -26402,10 +26616,19 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
26402
26616
  });
26403
26617
  }
26404
26618
 
26405
- var listener = function() {
26619
+ var listener = function(ev) {
26406
26620
  if (composing) return;
26407
26621
  var value = element.val();
26408
26622
 
26623
+ // IE (11 and under) seem to emit an 'input' event if the placeholder value changes.
26624
+ // We don't want to dirty the value when this happens, so we abort here. Unfortunately,
26625
+ // IE also sends input events for other non-input-related things, (such as focusing on a
26626
+ // form control), so this change is not entirely enough to solve this.
26627
+ if (msie && (ev || noevent).type === 'input' && element[0].placeholder !== placeholder) {
26628
+ placeholder = element[0].placeholder;
26629
+ return;
26630
+ }
26631
+
26409
26632
  // By default we will trim the value
26410
26633
  // If the attribute ng-trim exists we will avoid trimming
26411
26634
  // e.g. <input ng-model="foo" ng-trim="false">
@@ -26669,6 +26892,7 @@ function checkboxInputType(scope, element, attr, ctrl) {
26669
26892
  * patterns defined as scope expressions.
26670
26893
  * @param {string=} ngChange Angular expression to be executed when input changes due to user
26671
26894
  * interaction with the input element.
26895
+ * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
26672
26896
  */
26673
26897
 
26674
26898
 
@@ -26818,14 +27042,14 @@ var VALID_CLASS = 'ng-valid',
26818
27042
  * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever
26819
27043
  the model value changes. Each function is called, in turn, passing the value through to the
26820
27044
  next. Used to format / convert values for display in the control and validation.
26821
- * ```js
26822
- * function formatter(value) {
26823
- * if (value) {
26824
- * return value.toUpperCase();
26825
- * }
26826
- * }
26827
- * ngModel.$formatters.push(formatter);
26828
- * ```
27045
+ * ```js
27046
+ * function formatter(value) {
27047
+ * if (value) {
27048
+ * return value.toUpperCase();
27049
+ * }
27050
+ * }
27051
+ * ngModel.$formatters.push(formatter);
27052
+ * ```
26829
27053
  *
26830
27054
  * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the
26831
27055
  * view value has changed. It is called with no arguments, and its return value is ignored.
@@ -26854,7 +27078,12 @@ var VALID_CLASS = 'ng-valid',
26854
27078
  * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element
26855
27079
  * contents be edited in place by the user. This will not work on older browsers.
26856
27080
  *
26857
- * <example name="NgModelController" module="customControl">
27081
+ * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}
27082
+ * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`).
27083
+ * However, as we are using `$sce` the model can still decide to to provide unsafe content if it marks
27084
+ * that content using the `$sce` service.
27085
+ *
27086
+ * <example name="NgModelController" module="customControl" deps="angular-sanitize.js">
26858
27087
  <file name="style.css">
26859
27088
  [contenteditable] {
26860
27089
  border: 1px solid black;
@@ -26868,8 +27097,8 @@ var VALID_CLASS = 'ng-valid',
26868
27097
 
26869
27098
  </file>
26870
27099
  <file name="script.js">
26871
- angular.module('customControl', []).
26872
- directive('contenteditable', function() {
27100
+ angular.module('customControl', ['ngSanitize']).
27101
+ directive('contenteditable', ['$sce', function($sce) {
26873
27102
  return {
26874
27103
  restrict: 'A', // only activate on element attribute
26875
27104
  require: '?ngModel', // get a hold of NgModelController
@@ -26878,7 +27107,7 @@ var VALID_CLASS = 'ng-valid',
26878
27107
 
26879
27108
  // Specify how UI should be updated
26880
27109
  ngModel.$render = function() {
26881
- element.html(ngModel.$viewValue || '');
27110
+ element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
26882
27111
  };
26883
27112
 
26884
27113
  // Listen for change events to enable binding
@@ -26899,7 +27128,7 @@ var VALID_CLASS = 'ng-valid',
26899
27128
  }
26900
27129
  }
26901
27130
  };
26902
- });
27131
+ }]);
26903
27132
  </file>
26904
27133
  <file name="index.html">
26905
27134
  <form name="myForm">
@@ -27573,14 +27802,19 @@ var ngValueDirective = function() {
27573
27802
  </file>
27574
27803
  </example>
27575
27804
  */
27576
- var ngBindDirective = ngDirective(function(scope, element, attr) {
27577
- element.addClass('ng-binding').data('$binding', attr.ngBind);
27578
- scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
27579
- // We are purposefully using == here rather than === because we want to
27580
- // catch when value is "null or undefined"
27581
- // jshint -W041
27582
- element.text(value == undefined ? '' : value);
27583
- });
27805
+ var ngBindDirective = ngDirective({
27806
+ compile: function(templateElement) {
27807
+ templateElement.addClass('ng-binding');
27808
+ return function (scope, element, attr) {
27809
+ element.data('$binding', attr.ngBind);
27810
+ scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
27811
+ // We are purposefully using == here rather than === because we want to
27812
+ // catch when value is "null or undefined"
27813
+ // jshint -W041
27814
+ element.text(value == undefined ? '' : value);
27815
+ });
27816
+ };
27817
+ }
27584
27818
  });
27585
27819
 
27586
27820
 
@@ -27724,7 +27958,7 @@ function classDirective(name, selector) {
27724
27958
  scope.$watch('$index', function($index, old$index) {
27725
27959
  // jshint bitwise: false
27726
27960
  var mod = $index & 1;
27727
- if (mod !== old$index & 1) {
27961
+ if (mod !== (old$index & 1)) {
27728
27962
  var classes = arrayClasses(scope.$eval(attr[name]));
27729
27963
  mod === selector ?
27730
27964
  addClasses(classes) :
@@ -27783,7 +28017,7 @@ function classDirective(name, selector) {
27783
28017
  updateClasses(oldClasses, newClasses);
27784
28018
  }
27785
28019
  }
27786
- oldVal = copy(newVal);
28020
+ oldVal = shallowCopy(newVal);
27787
28021
  }
27788
28022
  }
27789
28023
  };
@@ -27811,7 +28045,7 @@ function classDirective(name, selector) {
27811
28045
  var classes = [], i = 0;
27812
28046
  forEach(classVal, function(v, k) {
27813
28047
  if (v) {
27814
- classes.push(k);
28048
+ classes = classes.concat(k.split(' '));
27815
28049
  }
27816
28050
  });
27817
28051
  return classes;
@@ -28136,7 +28370,7 @@ var ngCloakDirective = ngDirective({
28136
28370
  *
28137
28371
  * MVC components in angular:
28138
28372
  *
28139
- * * Model — The Model is scope properties; scopes are attached to the DOM where scope properties
28373
+ * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties
28140
28374
  * are accessed through bindings.
28141
28375
  * * View — The template (HTML with data bindings) that is rendered into the View.
28142
28376
  * * Controller — The `ngController` directive specifies a Controller class; the class contains business
@@ -28157,165 +28391,186 @@ var ngCloakDirective = ngDirective({
28157
28391
  * @example
28158
28392
  * Here is a simple form for editing user contact information. Adding, removing, clearing, and
28159
28393
  * greeting are methods declared on the controller (see source tab). These methods can
28160
- * easily be called from the angular markup. Notice that the scope becomes the `this` for the
28161
- * controller's instance. This allows for easy access to the view data from the controller. Also
28162
- * notice that any changes to the data are automatically reflected in the View without the need
28163
- * for a manual update. The example is shown in two different declaration styles you may use
28164
- * according to preference.
28165
- <example>
28166
- <file name="index.html">
28167
- <script>
28168
- function SettingsController1() {
28169
- this.name = "John Smith";
28170
- this.contacts = [
28171
- {type: 'phone', value: '408 555 1212'},
28172
- {type: 'email', value: 'john.smith@example.org'} ];
28173
- };
28174
-
28175
- SettingsController1.prototype.greet = function() {
28176
- alert(this.name);
28177
- };
28178
-
28179
- SettingsController1.prototype.addContact = function() {
28180
- this.contacts.push({type: 'email', value: 'yourname@example.org'});
28181
- };
28182
-
28183
- SettingsController1.prototype.removeContact = function(contactToRemove) {
28184
- var index = this.contacts.indexOf(contactToRemove);
28185
- this.contacts.splice(index, 1);
28186
- };
28187
-
28188
- SettingsController1.prototype.clearContact = function(contact) {
28189
- contact.type = 'phone';
28190
- contact.value = '';
28191
- };
28192
- </script>
28193
- <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
28194
- Name: <input type="text" ng-model="settings.name"/>
28195
- [ <a href="" ng-click="settings.greet()">greet</a> ]<br/>
28196
- Contact:
28197
- <ul>
28198
- <li ng-repeat="contact in settings.contacts">
28199
- <select ng-model="contact.type">
28200
- <option>phone</option>
28201
- <option>email</option>
28202
- </select>
28203
- <input type="text" ng-model="contact.value"/>
28204
- [ <a href="" ng-click="settings.clearContact(contact)">clear</a>
28205
- | <a href="" ng-click="settings.removeContact(contact)">X</a> ]
28206
- </li>
28207
- <li>[ <a href="" ng-click="settings.addContact()">add</a> ]</li>
28208
- </ul>
28209
- </div>
28210
- </file>
28211
- <file name="protractor.js" type="protractor">
28212
- it('should check controller as', function() {
28213
- var container = element(by.id('ctrl-as-exmpl'));
28214
-
28215
- expect(container.findElement(by.model('settings.name'))
28216
- .getAttribute('value')).toBe('John Smith');
28217
-
28218
- var firstRepeat =
28219
- container.findElement(by.repeater('contact in settings.contacts').row(0));
28220
- var secondRepeat =
28221
- container.findElement(by.repeater('contact in settings.contacts').row(1));
28222
-
28223
- expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
28224
- .toBe('408 555 1212');
28225
- expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value'))
28226
- .toBe('john.smith@example.org');
28227
-
28228
- firstRepeat.findElement(by.linkText('clear')).click();
28229
-
28230
- expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
28231
- .toBe('');
28232
-
28233
- container.findElement(by.linkText('add')).click();
28234
-
28235
- expect(container.findElement(by.repeater('contact in settings.contacts').row(2))
28236
- .findElement(by.model('contact.value'))
28237
- .getAttribute('value'))
28238
- .toBe('yourname@example.org');
28239
- });
28240
- </file>
28241
- </example>
28242
- <example>
28243
- <file name="index.html">
28244
- <script>
28245
- function SettingsController2($scope) {
28246
- $scope.name = "John Smith";
28247
- $scope.contacts = [
28248
- {type:'phone', value:'408 555 1212'},
28249
- {type:'email', value:'john.smith@example.org'} ];
28250
-
28251
- $scope.greet = function() {
28252
- alert(this.name);
28253
- };
28254
-
28255
- $scope.addContact = function() {
28256
- this.contacts.push({type:'email', value:'yourname@example.org'});
28257
- };
28258
-
28259
- $scope.removeContact = function(contactToRemove) {
28260
- var index = this.contacts.indexOf(contactToRemove);
28261
- this.contacts.splice(index, 1);
28262
- };
28263
-
28264
- $scope.clearContact = function(contact) {
28265
- contact.type = 'phone';
28266
- contact.value = '';
28267
- };
28268
- }
28269
- </script>
28270
- <div id="ctrl-exmpl" ng-controller="SettingsController2">
28271
- Name: <input type="text" ng-model="name"/>
28272
- [ <a href="" ng-click="greet()">greet</a> ]<br/>
28273
- Contact:
28274
- <ul>
28275
- <li ng-repeat="contact in contacts">
28276
- <select ng-model="contact.type">
28277
- <option>phone</option>
28278
- <option>email</option>
28279
- </select>
28280
- <input type="text" ng-model="contact.value"/>
28281
- [ <a href="" ng-click="clearContact(contact)">clear</a>
28282
- | <a href="" ng-click="removeContact(contact)">X</a> ]
28283
- </li>
28284
- <li>[ <a href="" ng-click="addContact()">add</a> ]</li>
28285
- </ul>
28286
- </div>
28287
- </file>
28288
- <file name="protractor.js" type="protractor">
28289
- it('should check controller', function() {
28290
- var container = element(by.id('ctrl-exmpl'));
28291
-
28292
- expect(container.findElement(by.model('name'))
28293
- .getAttribute('value')).toBe('John Smith');
28294
-
28295
- var firstRepeat =
28296
- container.findElement(by.repeater('contact in contacts').row(0));
28297
- var secondRepeat =
28298
- container.findElement(by.repeater('contact in contacts').row(1));
28299
-
28300
- expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
28301
- .toBe('408 555 1212');
28302
- expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value'))
28303
- .toBe('john.smith@example.org');
28304
-
28305
- firstRepeat.findElement(by.linkText('clear')).click();
28306
-
28307
- expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
28308
- .toBe('');
28309
-
28310
- container.findElement(by.linkText('add')).click();
28311
-
28312
- expect(container.findElement(by.repeater('contact in contacts').row(2))
28313
- .findElement(by.model('contact.value'))
28314
- .getAttribute('value'))
28315
- .toBe('yourname@example.org');
28316
- });
28317
- </file>
28318
- </example>
28394
+ * easily be called from the angular markup. Any changes to the data are automatically reflected
28395
+ * in the View without the need for a manual update.
28396
+ *
28397
+ * Two different declaration styles are included below:
28398
+ *
28399
+ * * one binds methods and properties directly onto the controller using `this`:
28400
+ * `ng-controller="SettingsController1 as settings"`
28401
+ * * one injects `$scope` into the controller:
28402
+ * `ng-controller="SettingsController2"`
28403
+ *
28404
+ * The second option is more common in the Angular community, and is generally used in boilerplates
28405
+ * and in this guide. However, there are advantages to binding properties directly to the controller
28406
+ * and avoiding scope.
28407
+ *
28408
+ * * Using `controller as` makes it obvious which controller you are accessing in the template when
28409
+ * multiple controllers apply to an element.
28410
+ * * If you are writing your controllers as classes you have easier access to the properties and
28411
+ * methods, which will appear on the scope, from inside the controller code.
28412
+ * * Since there is always a `.` in the bindings, you don't have to worry about prototypal
28413
+ * inheritance masking primitives.
28414
+ *
28415
+ * This example demonstrates the `controller as` syntax.
28416
+ *
28417
+ * <example name="ngControllerAs">
28418
+ * <file name="index.html">
28419
+ * <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
28420
+ * Name: <input type="text" ng-model="settings.name"/>
28421
+ * [ <a href="" ng-click="settings.greet()">greet</a> ]<br/>
28422
+ * Contact:
28423
+ * <ul>
28424
+ * <li ng-repeat="contact in settings.contacts">
28425
+ * <select ng-model="contact.type">
28426
+ * <option>phone</option>
28427
+ * <option>email</option>
28428
+ * </select>
28429
+ * <input type="text" ng-model="contact.value"/>
28430
+ * [ <a href="" ng-click="settings.clearContact(contact)">clear</a>
28431
+ * | <a href="" ng-click="settings.removeContact(contact)">X</a> ]
28432
+ * </li>
28433
+ * <li>[ <a href="" ng-click="settings.addContact()">add</a> ]</li>
28434
+ * </ul>
28435
+ * </div>
28436
+ * </file>
28437
+ * <file name="app.js">
28438
+ * function SettingsController1() {
28439
+ * this.name = "John Smith";
28440
+ * this.contacts = [
28441
+ * {type: 'phone', value: '408 555 1212'},
28442
+ * {type: 'email', value: 'john.smith@example.org'} ];
28443
+ * }
28444
+ *
28445
+ * SettingsController1.prototype.greet = function() {
28446
+ * alert(this.name);
28447
+ * };
28448
+ *
28449
+ * SettingsController1.prototype.addContact = function() {
28450
+ * this.contacts.push({type: 'email', value: 'yourname@example.org'});
28451
+ * };
28452
+ *
28453
+ * SettingsController1.prototype.removeContact = function(contactToRemove) {
28454
+ * var index = this.contacts.indexOf(contactToRemove);
28455
+ * this.contacts.splice(index, 1);
28456
+ * };
28457
+ *
28458
+ * SettingsController1.prototype.clearContact = function(contact) {
28459
+ * contact.type = 'phone';
28460
+ * contact.value = '';
28461
+ * };
28462
+ * </file>
28463
+ * <file name="protractor.js" type="protractor">
28464
+ * it('should check controller as', function() {
28465
+ * var container = element(by.id('ctrl-as-exmpl'));
28466
+ * expect(container.findElement(by.model('settings.name'))
28467
+ * .getAttribute('value')).toBe('John Smith');
28468
+ *
28469
+ * var firstRepeat =
28470
+ * container.findElement(by.repeater('contact in settings.contacts').row(0));
28471
+ * var secondRepeat =
28472
+ * container.findElement(by.repeater('contact in settings.contacts').row(1));
28473
+ *
28474
+ * expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
28475
+ * .toBe('408 555 1212');
28476
+ *
28477
+ * expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value'))
28478
+ * .toBe('john.smith@example.org');
28479
+ *
28480
+ * firstRepeat.findElement(by.linkText('clear')).click();
28481
+ *
28482
+ * expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
28483
+ * .toBe('');
28484
+ *
28485
+ * container.findElement(by.linkText('add')).click();
28486
+ *
28487
+ * expect(container.findElement(by.repeater('contact in settings.contacts').row(2))
28488
+ * .findElement(by.model('contact.value'))
28489
+ * .getAttribute('value'))
28490
+ * .toBe('yourname@example.org');
28491
+ * });
28492
+ * </file>
28493
+ * </example>
28494
+ *
28495
+ * This example demonstrates the "attach to `$scope`" style of controller.
28496
+ *
28497
+ * <example name="ngController">
28498
+ * <file name="index.html">
28499
+ * <div id="ctrl-exmpl" ng-controller="SettingsController2">
28500
+ * Name: <input type="text" ng-model="name"/>
28501
+ * [ <a href="" ng-click="greet()">greet</a> ]<br/>
28502
+ * Contact:
28503
+ * <ul>
28504
+ * <li ng-repeat="contact in contacts">
28505
+ * <select ng-model="contact.type">
28506
+ * <option>phone</option>
28507
+ * <option>email</option>
28508
+ * </select>
28509
+ * <input type="text" ng-model="contact.value"/>
28510
+ * [ <a href="" ng-click="clearContact(contact)">clear</a>
28511
+ * | <a href="" ng-click="removeContact(contact)">X</a> ]
28512
+ * </li>
28513
+ * <li>[ <a href="" ng-click="addContact()">add</a> ]</li>
28514
+ * </ul>
28515
+ * </div>
28516
+ * </file>
28517
+ * <file name="app.js">
28518
+ * function SettingsController2($scope) {
28519
+ * $scope.name = "John Smith";
28520
+ * $scope.contacts = [
28521
+ * {type:'phone', value:'408 555 1212'},
28522
+ * {type:'email', value:'john.smith@example.org'} ];
28523
+ *
28524
+ * $scope.greet = function() {
28525
+ * alert($scope.name);
28526
+ * };
28527
+ *
28528
+ * $scope.addContact = function() {
28529
+ * $scope.contacts.push({type:'email', value:'yourname@example.org'});
28530
+ * };
28531
+ *
28532
+ * $scope.removeContact = function(contactToRemove) {
28533
+ * var index = $scope.contacts.indexOf(contactToRemove);
28534
+ * $scope.contacts.splice(index, 1);
28535
+ * };
28536
+ *
28537
+ * $scope.clearContact = function(contact) {
28538
+ * contact.type = 'phone';
28539
+ * contact.value = '';
28540
+ * };
28541
+ * }
28542
+ * </file>
28543
+ * <file name="protractor.js" type="protractor">
28544
+ * it('should check controller', function() {
28545
+ * var container = element(by.id('ctrl-exmpl'));
28546
+ *
28547
+ * expect(container.findElement(by.model('name'))
28548
+ * .getAttribute('value')).toBe('John Smith');
28549
+ *
28550
+ * var firstRepeat =
28551
+ * container.findElement(by.repeater('contact in contacts').row(0));
28552
+ * var secondRepeat =
28553
+ * container.findElement(by.repeater('contact in contacts').row(1));
28554
+ *
28555
+ * expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
28556
+ * .toBe('408 555 1212');
28557
+ * expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value'))
28558
+ * .toBe('john.smith@example.org');
28559
+ *
28560
+ * firstRepeat.findElement(by.linkText('clear')).click();
28561
+ *
28562
+ * expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
28563
+ * .toBe('');
28564
+ *
28565
+ * container.findElement(by.linkText('add')).click();
28566
+ *
28567
+ * expect(container.findElement(by.repeater('contact in contacts').row(2))
28568
+ * .findElement(by.model('contact.value'))
28569
+ * .getAttribute('value'))
28570
+ * .toBe('yourname@example.org');
28571
+ * });
28572
+ * </file>
28573
+ *</example>
28319
28574
 
28320
28575
  */
28321
28576
  var ngControllerDirective = [function() {
@@ -28413,7 +28668,7 @@ forEach(
28413
28668
  return {
28414
28669
  compile: function($element, attr) {
28415
28670
  var fn = $parse(attr[directiveName]);
28416
- return function(scope, element, attr) {
28671
+ return function ngEventHandler(scope, element) {
28417
28672
  element.on(lowercase(name), function(event) {
28418
28673
  scope.$apply(function() {
28419
28674
  fn(scope, {$event:event});
@@ -28630,8 +28885,13 @@ forEach(
28630
28885
  * @example
28631
28886
  <example>
28632
28887
  <file name="index.html">
28633
- <input ng-keyup="count = count + 1" ng-init="count=0">
28634
- key up count: {{count}}
28888
+ <p>Typing in the input box below updates the key count</p>
28889
+ <input ng-keyup="count = count + 1" ng-init="count=0"> key up count: {{count}}
28890
+
28891
+ <p>Typing in the input box below updates the keycode</p>
28892
+ <input ng-keyup="event=$event">
28893
+ <p>event keyCode: {{ event.keyCode }}</p>
28894
+ <p>event altKey: {{ event.altKey }}</p>
28635
28895
  </file>
28636
28896
  </example>
28637
28897
  */
@@ -28903,7 +29163,7 @@ var ngIfDirective = ['$animate', function($animate) {
28903
29163
  clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
28904
29164
  // Note: We only need the first/last node of the cloned nodes.
28905
29165
  // However, we need to keep the reference to the jqlite wrapper as it might be changed later
28906
- // by a directive with templateUrl when it's template arrives.
29166
+ // by a directive with templateUrl when its template arrives.
28907
29167
  block = {
28908
29168
  clone: clone
28909
29169
  };
@@ -29602,7 +29862,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp
29602
29862
  * mapped to the same DOM element, which is not possible.) Filters should be applied to the expression,
29603
29863
  * before specifying a tracking expression.
29604
29864
  *
29605
- * For example: `item in items` is equivalent to `item in items track by $id(item)'. This implies that the DOM elements
29865
+ * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
29606
29866
  * will be associated by item identity in the array.
29607
29867
  *
29608
29868
  * For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
@@ -29880,7 +30140,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
29880
30140
  block.scope = childScope;
29881
30141
  // Note: We only need the first/last node of the cloned nodes.
29882
30142
  // However, we need to keep the reference to the jqlite wrapper as it might be changed later
29883
- // by a directive with templateUrl when it's template arrives.
30143
+ // by a directive with templateUrl when its template arrives.
29884
30144
  block.clone = clone;
29885
30145
  nextBlockMap[block.id] = block;
29886
30146
  });
@@ -29923,6 +30183,11 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
29923
30183
  * on the element causing it to become hidden. When true, the ng-hide CSS class is removed
29924
30184
  * from the element causing the element not to appear hidden.
29925
30185
  *
30186
+ * <div class="alert alert-warning">
30187
+ * **Note:** Here is a list of values that ngShow will consider as a falsy value (case insensitive):<br />
30188
+ * "f" / "0" / "false" / "no" / "n" / "[]"
30189
+ * </div>
30190
+ *
29926
30191
  * ## Why is !important used?
29927
30192
  *
29928
30193
  * You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
@@ -29936,26 +30201,21 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
29936
30201
  *
29937
30202
  * ### Overriding .ng-hide
29938
30203
  *
29939
- * If you wish to change the hide behavior with ngShow/ngHide then this can be achieved by
29940
- * restating the styles for the .ng-hide class in CSS:
30204
+ * By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change
30205
+ * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
30206
+ * class in CSS:
30207
+ *
29941
30208
  * ```css
29942
30209
  * .ng-hide {
29943
- * //!annotate CSS Specificity|Not to worry, this will override the AngularJS default...
29944
- * display:block!important;
29945
- *
29946
30210
  * //this is just another form of hiding an element
30211
+ * display:block!important;
29947
30212
  * position:absolute;
29948
30213
  * top:-9999px;
29949
30214
  * left:-9999px;
29950
30215
  * }
29951
30216
  * ```
29952
30217
  *
29953
- * Just remember to include the important flag so the CSS override will function.
29954
- *
29955
- * <div class="alert alert-warning">
29956
- * **Note:** Here is a list of values that ngShow will consider as a falsy value (case insensitive):<br />
29957
- * "f" / "0" / "false" / "no" / "n" / "[]"
29958
- * </div>
30218
+ * By default you don't need to override in CSS anything and the animations will work around the display style.
29959
30219
  *
29960
30220
  * ## A note about animations with ngShow
29961
30221
  *
@@ -29970,7 +30230,6 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
29970
30230
  * //
29971
30231
  * .my-element.ng-hide-add, .my-element.ng-hide-remove {
29972
30232
  * transition:0.5s linear all;
29973
- * display:block!important;
29974
30233
  * }
29975
30234
  *
29976
30235
  * .my-element.ng-hide-add { ... }
@@ -29979,6 +30238,9 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
29979
30238
  * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
29980
30239
  * ```
29981
30240
  *
30241
+ * Keep in mind that, as of AngularJS version 1.2.17 (and 1.3.0-beta.11), there is no need to change the display
30242
+ * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
30243
+ *
29982
30244
  * @animations
29983
30245
  * addClass: .ng-hide - happens after the ngShow expression evaluates to a truthy value and the just before contents are set to visible
29984
30246
  * removeClass: .ng-hide - happens after the ngShow expression evaluates to a non truthy value and just before the contents are set to hidden
@@ -30018,11 +30280,6 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
30018
30280
  background:white;
30019
30281
  }
30020
30282
 
30021
- .animate-show.ng-hide-add,
30022
- .animate-show.ng-hide-remove {
30023
- display:block!important;
30024
- }
30025
-
30026
30283
  .animate-show.ng-hide {
30027
30284
  line-height:0;
30028
30285
  opacity:0;
@@ -30073,16 +30330,21 @@ var ngShowDirective = ['$animate', function($animate) {
30073
30330
  *
30074
30331
  * ```html
30075
30332
  * <!-- when $scope.myValue is truthy (element is hidden) -->
30076
- * <div ng-hide="myValue"></div>
30333
+ * <div ng-hide="myValue" class="ng-hide"></div>
30077
30334
  *
30078
30335
  * <!-- when $scope.myValue is falsy (element is visible) -->
30079
- * <div ng-hide="myValue" class="ng-hide"></div>
30336
+ * <div ng-hide="myValue"></div>
30080
30337
  * ```
30081
30338
  *
30082
30339
  * When the ngHide expression evaluates to true then the .ng-hide CSS class is added to the class attribute
30083
30340
  * on the element causing it to become hidden. When false, the ng-hide CSS class is removed
30084
30341
  * from the element causing the element not to appear hidden.
30085
30342
  *
30343
+ * <div class="alert alert-warning">
30344
+ * **Note:** Here is a list of values that ngHide will consider as a falsy value (case insensitive):<br />
30345
+ * "f" / "0" / "false" / "no" / "n" / "[]"
30346
+ * </div>
30347
+ *
30086
30348
  * ## Why is !important used?
30087
30349
  *
30088
30350
  * You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
@@ -30096,33 +30358,27 @@ var ngShowDirective = ['$animate', function($animate) {
30096
30358
  *
30097
30359
  * ### Overriding .ng-hide
30098
30360
  *
30099
- * If you wish to change the hide behavior with ngShow/ngHide then this can be achieved by
30100
- * restating the styles for the .ng-hide class in CSS:
30361
+ * By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change
30362
+ * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
30363
+ * class in CSS:
30364
+ *
30101
30365
  * ```css
30102
30366
  * .ng-hide {
30103
- * //!annotate CSS Specificity|Not to worry, this will override the AngularJS default...
30104
- * display:block!important;
30105
- *
30106
30367
  * //this is just another form of hiding an element
30368
+ * display:block!important;
30107
30369
  * position:absolute;
30108
30370
  * top:-9999px;
30109
30371
  * left:-9999px;
30110
30372
  * }
30111
30373
  * ```
30112
30374
  *
30113
- * Just remember to include the important flag so the CSS override will function.
30114
- *
30115
- * <div class="alert alert-warning">
30116
- * **Note:** Here is a list of values that ngHide will consider as a falsy value (case insensitive):<br />
30117
- * "f" / "0" / "false" / "no" / "n" / "[]"
30118
- * </div>
30375
+ * By default you don't need to override in CSS anything and the animations will work around the display style.
30119
30376
  *
30120
30377
  * ## A note about animations with ngHide
30121
30378
  *
30122
30379
  * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
30123
- * is true and false. This system works like the animation system present with ngClass, except that
30124
- * you must also include the !important flag to override the display property so
30125
- * that you can perform an animation when the element is hidden during the time of the animation.
30380
+ * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`
30381
+ * CSS class is added and removed for you instead of your own CSS class.
30126
30382
  *
30127
30383
  * ```css
30128
30384
  * //
@@ -30130,7 +30386,6 @@ var ngShowDirective = ['$animate', function($animate) {
30130
30386
  * //
30131
30387
  * .my-element.ng-hide-add, .my-element.ng-hide-remove {
30132
30388
  * transition:0.5s linear all;
30133
- * display:block!important;
30134
30389
  * }
30135
30390
  *
30136
30391
  * .my-element.ng-hide-add { ... }
@@ -30139,6 +30394,9 @@ var ngShowDirective = ['$animate', function($animate) {
30139
30394
  * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
30140
30395
  * ```
30141
30396
  *
30397
+ * Keep in mind that, as of AngularJS version 1.2.17 (and 1.3.0-beta.11), there is no need to change the display
30398
+ * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
30399
+ *
30142
30400
  * @animations
30143
30401
  * removeClass: .ng-hide - happens after the ngHide expression evaluates to a truthy value and just before the contents are set to hidden
30144
30402
  * addClass: .ng-hide - happens after the ngHide expression evaluates to a non truthy value and just before the contents are set to visible
@@ -30178,11 +30436,6 @@ var ngShowDirective = ['$animate', function($animate) {
30178
30436
  background:white;
30179
30437
  }
30180
30438
 
30181
- .animate-hide.ng-hide-add,
30182
- .animate-hide.ng-hide-remove {
30183
- display:block!important;
30184
- }
30185
-
30186
30439
  .animate-hide.ng-hide {
30187
30440
  line-height:0;
30188
30441
  opacity:0;
@@ -30228,14 +30481,20 @@ var ngHideDirective = ['$animate', function($animate) {
30228
30481
  * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.
30229
30482
  *
30230
30483
  * @element ANY
30231
- * @param {expression} ngStyle {@link guide/expression Expression} which evals to an
30232
- * object whose keys are CSS style names and values are corresponding values for those CSS
30233
- * keys.
30484
+ * @param {expression} ngStyle
30485
+ *
30486
+ * {@link guide/expression Expression} which evals to an
30487
+ * object whose keys are CSS style names and values are corresponding values for those CSS
30488
+ * keys.
30489
+ *
30490
+ * Since some CSS style names are not valid keys for an object, they must be quoted.
30491
+ * See the 'background-color' style in the example below.
30234
30492
  *
30235
30493
  * @example
30236
30494
  <example>
30237
30495
  <file name="index.html">
30238
- <input type="button" value="set" ng-click="myStyle={color:'red'}">
30496
+ <input type="button" value="set color" ng-click="myStyle={color:'red'}">
30497
+ <input type="button" value="set background" ng-click="myStyle={'background-color':'blue'}">
30239
30498
  <input type="button" value="clear" ng-click="myStyle={}">
30240
30499
  <br/>
30241
30500
  <span ng-style="myStyle">Sample Text</span>
@@ -30249,9 +30508,9 @@ var ngHideDirective = ['$animate', function($animate) {
30249
30508
  <file name="protractor.js" type="protractor">
30250
30509
  var colorSpan = element(by.css('span'));
30251
30510
 
30252
- it('should check ng-style', function() {
30511
+ iit('should check ng-style', function() {
30253
30512
  expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
30254
- element(by.css('input[value=set]')).click();
30513
+ element(by.css('input[value=\'set color\']')).click();
30255
30514
  expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');
30256
30515
  element(by.css('input[value=clear]')).click();
30257
30516
  expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
@@ -30299,11 +30558,14 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
30299
30558
  * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM
30300
30559
  *
30301
30560
  * @usage
30561
+ *
30562
+ * ```
30302
30563
  * <ANY ng-switch="expression">
30303
30564
  * <ANY ng-switch-when="matchValue1">...</ANY>
30304
30565
  * <ANY ng-switch-when="matchValue2">...</ANY>
30305
30566
  * <ANY ng-switch-default>...</ANY>
30306
30567
  * </ANY>
30568
+ * ```
30307
30569
  *
30308
30570
  *
30309
30571
  * @scope
@@ -30403,37 +30665,29 @@ var ngSwitchDirective = ['$animate', function($animate) {
30403
30665
  }],
30404
30666
  link: function(scope, element, attr, ngSwitchController) {
30405
30667
  var watchExpr = attr.ngSwitch || attr.on,
30406
- selectedTranscludes,
30407
- selectedElements,
30408
- previousElements,
30668
+ selectedTranscludes = [],
30669
+ selectedElements = [],
30670
+ previousElements = [],
30409
30671
  selectedScopes = [];
30410
30672
 
30411
30673
  scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
30412
- var i, ii = selectedScopes.length;
30413
- if(ii > 0) {
30414
- if(previousElements) {
30415
- for (i = 0; i < ii; i++) {
30416
- previousElements[i].remove();
30417
- }
30418
- previousElements = null;
30419
- }
30420
-
30421
- previousElements = [];
30422
- for (i= 0; i<ii; i++) {
30423
- var selected = selectedElements[i];
30424
- selectedScopes[i].$destroy();
30425
- previousElements[i] = selected;
30426
- $animate.leave(selected, function() {
30427
- previousElements.splice(i, 1);
30428
- if(previousElements.length === 0) {
30429
- previousElements = null;
30430
- }
30431
- });
30432
- }
30674
+ var i, ii;
30675
+ for (i = 0, ii = previousElements.length; i < ii; ++i) {
30676
+ previousElements[i].remove();
30677
+ }
30678
+ previousElements.length = 0;
30679
+
30680
+ for (i = 0, ii = selectedScopes.length; i < ii; ++i) {
30681
+ var selected = selectedElements[i];
30682
+ selectedScopes[i].$destroy();
30683
+ previousElements[i] = selected;
30684
+ $animate.leave(selected, function() {
30685
+ previousElements.splice(i, 1);
30686
+ });
30433
30687
  }
30434
30688
 
30435
- selectedElements = [];
30436
- selectedScopes = [];
30689
+ selectedElements.length = 0;
30690
+ selectedScopes.length = 0;
30437
30691
 
30438
30692
  if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
30439
30693
  scope.$eval(attr.change);
@@ -30677,7 +30931,7 @@ var ngOptionsMinErr = minErr('ngOptions');
30677
30931
  {name:'blue', shade:'dark'},
30678
30932
  {name:'yellow', shade:'light'}
30679
30933
  ];
30680
- $scope.color = $scope.colors[2]; // red
30934
+ $scope.myColor = $scope.colors[2]; // red
30681
30935
  }
30682
30936
  </script>
30683
30937
  <div ng-controller="MyCntrl">
@@ -30692,37 +30946,37 @@ var ngOptionsMinErr = minErr('ngOptions');
30692
30946
  </ul>
30693
30947
  <hr/>
30694
30948
  Color (null not allowed):
30695
- <select ng-model="color" ng-options="c.name for c in colors"></select><br>
30949
+ <select ng-model="myColor" ng-options="color.name for color in colors"></select><br>
30696
30950
 
30697
30951
  Color (null allowed):
30698
30952
  <span class="nullable">
30699
- <select ng-model="color" ng-options="c.name for c in colors">
30953
+ <select ng-model="myColor" ng-options="color.name for color in colors">
30700
30954
  <option value="">-- choose color --</option>
30701
30955
  </select>
30702
30956
  </span><br/>
30703
30957
 
30704
30958
  Color grouped by shade:
30705
- <select ng-model="color" ng-options="c.name group by c.shade for c in colors">
30959
+ <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors">
30706
30960
  </select><br/>
30707
30961
 
30708
30962
 
30709
- Select <a href ng-click="color={name:'not in list'}">bogus</a>.<br>
30963
+ Select <a href ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</a>.<br>
30710
30964
  <hr/>
30711
- Currently selected: {{ {selected_color:color} }}
30965
+ Currently selected: {{ {selected_color:myColor} }}
30712
30966
  <div style="border:solid 1px black; height:20px"
30713
- ng-style="{'background-color':color.name}">
30967
+ ng-style="{'background-color':myColor.name}">
30714
30968
  </div>
30715
30969
  </div>
30716
30970
  </file>
30717
30971
  <file name="protractor.js" type="protractor">
30718
30972
  it('should check ng-options', function() {
30719
- expect(element(by.binding('{selected_color:color}')).getText()).toMatch('red');
30720
- element.all(by.select('color')).first().click();
30721
- element.all(by.css('select[ng-model="color"] option')).first().click();
30722
- expect(element(by.binding('{selected_color:color}')).getText()).toMatch('black');
30723
- element(by.css('.nullable select[ng-model="color"]')).click();
30724
- element.all(by.css('.nullable select[ng-model="color"] option')).first().click();
30725
- expect(element(by.binding('{selected_color:color}')).getText()).toMatch('null');
30973
+ expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');
30974
+ element.all(by.select('myColor')).first().click();
30975
+ element.all(by.css('select[ng-model="myColor"] option')).first().click();
30976
+ expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');
30977
+ element(by.css('.nullable select[ng-model="myColor"]')).click();
30978
+ element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click();
30979
+ expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');
30726
30980
  });
30727
30981
  </file>
30728
30982
  </example>
@@ -30877,7 +31131,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
30877
31131
  // we need to work of an array, so we need to see if anything was inserted/removed
30878
31132
  scope.$watch(function selectMultipleWatch() {
30879
31133
  if (!equals(lastView, ctrl.$viewValue)) {
30880
- lastView = copy(ctrl.$viewValue);
31134
+ lastView = shallowCopy(ctrl.$viewValue);
30881
31135
  ctrl.$render();
30882
31136
  }
30883
31137
  });
@@ -32036,7 +32290,7 @@ angular.scenario.Future.prototype.execute = function(doneFn) {
32036
32290
  };
32037
32291
 
32038
32292
  /**
32039
- * Configures the future to convert it's final with a function fn(value)
32293
+ * Configures the future to convert its final with a function fn(value)
32040
32294
  *
32041
32295
  * @param {function()} fn function(value) that returns the parsed value
32042
32296
  */
@@ -32046,7 +32300,7 @@ angular.scenario.Future.prototype.parsedWith = function(fn) {
32046
32300
  };
32047
32301
 
32048
32302
  /**
32049
- * Configures the future to parse it's final value from JSON
32303
+ * Configures the future to parse its final value from JSON
32050
32304
  * into objects.
32051
32305
  */
32052
32306
  angular.scenario.Future.prototype.fromJson = function() {
@@ -32054,7 +32308,7 @@ angular.scenario.Future.prototype.fromJson = function() {
32054
32308
  };
32055
32309
 
32056
32310
  /**
32057
- * Configures the future to convert it's final value from objects
32311
+ * Configures the future to convert its final value from objects
32058
32312
  * into JSON.
32059
32313
  */
32060
32314
  angular.scenario.Future.prototype.toJson = function() {
@@ -33460,5 +33714,5 @@ if (config.autotest) {
33460
33714
  })(window, document);
33461
33715
 
33462
33716
 
33463
- !angular.$$csp() && angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";\n\n[ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\n.ng-cloak, .x-ng-cloak,\n.ng-hide {\n display: none !important;\n}\n\nng\\:form {\n display: block;\n}\n\n.ng-animate-block-transitions {\n transition:0s all!important;\n -webkit-transition:0s all!important;\n}\n</style>');
33464
- !angular.$$csp() && angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";\n/* CSS Document */\n\n/** Structure */\nbody {\n font-family: Arial, sans-serif;\n margin: 0;\n font-size: 14px;\n}\n\n#system-error {\n font-size: 1.5em;\n text-align: center;\n}\n\n#json, #xml {\n display: none;\n}\n\n#header {\n position: fixed;\n width: 100%;\n}\n\n#specs {\n padding-top: 50px;\n}\n\n#header .angular {\n font-family: Courier New, monospace;\n font-weight: bold;\n}\n\n#header h1 {\n font-weight: normal;\n float: left;\n font-size: 30px;\n line-height: 30px;\n margin: 0;\n padding: 10px 10px;\n height: 30px;\n}\n\n#application h2,\n#specs h2 {\n margin: 0;\n padding: 0.5em;\n font-size: 1.1em;\n}\n\n#status-legend {\n margin-top: 10px;\n margin-right: 10px;\n}\n\n#header,\n#application,\n.test-info,\n.test-actions li {\n overflow: hidden;\n}\n\n#application {\n margin: 10px;\n}\n\n#application iframe {\n width: 100%;\n height: 758px;\n}\n\n#application .popout {\n float: right;\n}\n\n#application iframe {\n border: none;\n}\n\n.tests li,\n.test-actions li,\n.test-it li,\n.test-it ol,\n.status-display {\n list-style-type: none;\n}\n\n.tests,\n.test-it ol,\n.status-display {\n margin: 0;\n padding: 0;\n}\n\n.test-info {\n margin-left: 1em;\n margin-top: 0.5em;\n border-radius: 8px 0 0 8px;\n -webkit-border-radius: 8px 0 0 8px;\n -moz-border-radius: 8px 0 0 8px;\n cursor: pointer;\n}\n\n.test-info:hover .test-name {\n text-decoration: underline;\n}\n\n.test-info .closed:before {\n content: \'\\25b8\\00A0\';\n}\n\n.test-info .open:before {\n content: \'\\25be\\00A0\';\n font-weight: bold;\n}\n\n.test-it ol {\n margin-left: 2.5em;\n}\n\n.status-display,\n.status-display li {\n float: right;\n}\n\n.status-display li {\n padding: 5px 10px;\n}\n\n.timer-result,\n.test-title {\n display: inline-block;\n margin: 0;\n padding: 4px;\n}\n\n.test-actions .test-title,\n.test-actions .test-result {\n display: table-cell;\n padding-left: 0.5em;\n padding-right: 0.5em;\n}\n\n.test-actions {\n display: table;\n}\n\n.test-actions li {\n display: table-row;\n}\n\n.timer-result {\n width: 4em;\n padding: 0 10px;\n text-align: right;\n font-family: monospace;\n}\n\n.test-it pre,\n.test-actions pre {\n clear: left;\n color: black;\n margin-left: 6em;\n}\n\n.test-describe {\n padding-bottom: 0.5em;\n}\n\n.test-describe .test-describe {\n margin: 5px 5px 10px 2em;\n}\n\n.test-actions .status-pending .test-title:before {\n content: \'\\00bb\\00A0\';\n}\n\n.scrollpane {\n max-height: 20em;\n overflow: auto;\n}\n\n/** Colors */\n\n#header {\n background-color: #F2C200;\n}\n\n#specs h2 {\n border-top: 2px solid #BABAD1;\n}\n\n#specs h2,\n#application h2 {\n background-color: #efefef;\n}\n\n#application {\n border: 1px solid #BABAD1;\n}\n\n.test-describe .test-describe {\n border-left: 1px solid #BABAD1;\n border-right: 1px solid #BABAD1;\n border-bottom: 1px solid #BABAD1;\n}\n\n.status-display {\n border: 1px solid #777;\n}\n\n.status-display .status-pending,\n.status-pending .test-info {\n background-color: #F9EEBC;\n}\n\n.status-display .status-success,\n.status-success .test-info {\n background-color: #B1D7A1;\n}\n\n.status-display .status-failure,\n.status-failure .test-info {\n background-color: #FF8286;\n}\n\n.status-display .status-error,\n.status-error .test-info {\n background-color: black;\n color: white;\n}\n\n.test-actions .status-success .test-title {\n color: #30B30A;\n}\n\n.test-actions .status-failure .test-title {\n color: #DF0000;\n}\n\n.test-actions .status-error .test-title {\n color: black;\n}\n\n.test-actions .timer-result {\n color: #888;\n}\n</style>');
33717
+ !window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";\n\n[ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\n.ng-cloak, .x-ng-cloak,\n.ng-hide {\n display: none !important;\n}\n\nng\\:form {\n display: block;\n}\n\n.ng-animate-block-transitions {\n transition:0s all!important;\n -webkit-transition:0s all!important;\n}\n\n/* show the element during a show/hide animation when the\n * animation is ongoing, but the .ng-hide class is active */\n.ng-hide-add-active, .ng-hide-remove {\n display: block!important;\n}\n</style>');
33718
+ !window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";\n/* CSS Document */\n\n/** Structure */\nbody {\n font-family: Arial, sans-serif;\n margin: 0;\n font-size: 14px;\n}\n\n#system-error {\n font-size: 1.5em;\n text-align: center;\n}\n\n#json, #xml {\n display: none;\n}\n\n#header {\n position: fixed;\n width: 100%;\n}\n\n#specs {\n padding-top: 50px;\n}\n\n#header .angular {\n font-family: Courier New, monospace;\n font-weight: bold;\n}\n\n#header h1 {\n font-weight: normal;\n float: left;\n font-size: 30px;\n line-height: 30px;\n margin: 0;\n padding: 10px 10px;\n height: 30px;\n}\n\n#application h2,\n#specs h2 {\n margin: 0;\n padding: 0.5em;\n font-size: 1.1em;\n}\n\n#status-legend {\n margin-top: 10px;\n margin-right: 10px;\n}\n\n#header,\n#application,\n.test-info,\n.test-actions li {\n overflow: hidden;\n}\n\n#application {\n margin: 10px;\n}\n\n#application iframe {\n width: 100%;\n height: 758px;\n}\n\n#application .popout {\n float: right;\n}\n\n#application iframe {\n border: none;\n}\n\n.tests li,\n.test-actions li,\n.test-it li,\n.test-it ol,\n.status-display {\n list-style-type: none;\n}\n\n.tests,\n.test-it ol,\n.status-display {\n margin: 0;\n padding: 0;\n}\n\n.test-info {\n margin-left: 1em;\n margin-top: 0.5em;\n border-radius: 8px 0 0 8px;\n -webkit-border-radius: 8px 0 0 8px;\n -moz-border-radius: 8px 0 0 8px;\n cursor: pointer;\n}\n\n.test-info:hover .test-name {\n text-decoration: underline;\n}\n\n.test-info .closed:before {\n content: \'\\25b8\\00A0\';\n}\n\n.test-info .open:before {\n content: \'\\25be\\00A0\';\n font-weight: bold;\n}\n\n.test-it ol {\n margin-left: 2.5em;\n}\n\n.status-display,\n.status-display li {\n float: right;\n}\n\n.status-display li {\n padding: 5px 10px;\n}\n\n.timer-result,\n.test-title {\n display: inline-block;\n margin: 0;\n padding: 4px;\n}\n\n.test-actions .test-title,\n.test-actions .test-result {\n display: table-cell;\n padding-left: 0.5em;\n padding-right: 0.5em;\n}\n\n.test-actions {\n display: table;\n}\n\n.test-actions li {\n display: table-row;\n}\n\n.timer-result {\n width: 4em;\n padding: 0 10px;\n text-align: right;\n font-family: monospace;\n}\n\n.test-it pre,\n.test-actions pre {\n clear: left;\n color: black;\n margin-left: 6em;\n}\n\n.test-describe {\n padding-bottom: 0.5em;\n}\n\n.test-describe .test-describe {\n margin: 5px 5px 10px 2em;\n}\n\n.test-actions .status-pending .test-title:before {\n content: \'\\00bb\\00A0\';\n}\n\n.scrollpane {\n max-height: 20em;\n overflow: auto;\n}\n\n/** Colors */\n\n#header {\n background-color: #F2C200;\n}\n\n#specs h2 {\n border-top: 2px solid #BABAD1;\n}\n\n#specs h2,\n#application h2 {\n background-color: #efefef;\n}\n\n#application {\n border: 1px solid #BABAD1;\n}\n\n.test-describe .test-describe {\n border-left: 1px solid #BABAD1;\n border-right: 1px solid #BABAD1;\n border-bottom: 1px solid #BABAD1;\n}\n\n.status-display {\n border: 1px solid #777;\n}\n\n.status-display .status-pending,\n.status-pending .test-info {\n background-color: #F9EEBC;\n}\n\n.status-display .status-success,\n.status-success .test-info {\n background-color: #B1D7A1;\n}\n\n.status-display .status-failure,\n.status-failure .test-info {\n background-color: #FF8286;\n}\n\n.status-display .status-error,\n.status-error .test-info {\n background-color: black;\n color: white;\n}\n\n.test-actions .status-success .test-title {\n color: #30B30A;\n}\n\n.test-actions .status-failure .test-title {\n color: #DF0000;\n}\n\n.test-actions .status-error .test-title {\n color: black;\n}\n\n.test-actions .timer-result {\n color: #888;\n}\n</style>');