angularjs-rails 1.2.16 → 1.2.18

Sign up to get free protection for your applications and to get access to all the features.
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>');