angularjs-rails 1.2.21 → 1.2.22

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.0-beta.17
2
+ * @license AngularJS v1.3.0-beta.18
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.3.0-beta.17
2
+ * @license AngularJS v1.3.0-beta.18
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -68,7 +68,7 @@ function minErr(module) {
68
68
  return match;
69
69
  });
70
70
 
71
- message = message + '\nhttp://errors.angularjs.org/1.3.0-beta.17/' +
71
+ message = message + '\nhttp://errors.angularjs.org/1.3.0-beta.18/' +
72
72
  (module ? module + '/' : '') + code;
73
73
  for (i = 2; i < arguments.length; i++) {
74
74
  message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
@@ -1255,6 +1255,7 @@ function encodeUriQuery(val, pctEncodeSpaces) {
1255
1255
  replace(/%3A/gi, ':').
1256
1256
  replace(/%24/g, '$').
1257
1257
  replace(/%2C/gi, ',').
1258
+ replace(/%3B/gi, ';').
1258
1259
  replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
1259
1260
  }
1260
1261
 
@@ -1537,7 +1538,9 @@ function bindJQuery() {
1537
1538
  // bind to jQuery if present;
1538
1539
  jQuery = window.jQuery;
1539
1540
  // Use jQuery if it exists with proper functionality, otherwise default to us.
1540
- // Angular 1.2+ requires jQuery 1.7.1+ for on()/off() support.
1541
+ // Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
1542
+ // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older
1543
+ // versions. It will not work for sure with jQuery <1.7, though.
1541
1544
  if (jQuery && jQuery.fn.on) {
1542
1545
  jqLite = jQuery;
1543
1546
  extend(jQuery.fn, {
@@ -2067,11 +2070,11 @@ function setupModuleLoader(window) {
2067
2070
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
2068
2071
  */
2069
2072
  var version = {
2070
- full: '1.3.0-beta.17', // all of these placeholder strings will be replaced by grunt's
2073
+ full: '1.3.0-beta.18', // all of these placeholder strings will be replaced by grunt's
2071
2074
  major: 1, // package task
2072
2075
  minor: 3,
2073
2076
  dot: 0,
2074
- codeName: 'turing-autocompletion'
2077
+ codeName: 'spontaneous-combustion'
2075
2078
  };
2076
2079
 
2077
2080
 
@@ -2084,11 +2087,11 @@ function publishExternalAPI(angular){
2084
2087
  'element': jqLite,
2085
2088
  'forEach': forEach,
2086
2089
  'injector': createInjector,
2087
- 'noop':noop,
2088
- 'bind':bind,
2090
+ 'noop': noop,
2091
+ 'bind': bind,
2089
2092
  'toJson': toJson,
2090
2093
  'fromJson': fromJson,
2091
- 'identity':identity,
2094
+ 'identity': identity,
2092
2095
  'isUndefined': isUndefined,
2093
2096
  'isDefined': isDefined,
2094
2097
  'isString': isString,
@@ -2451,7 +2454,7 @@ function jqLiteDealoc(element, onlyDescendants){
2451
2454
 
2452
2455
  if (element.childNodes && element.childNodes.length) {
2453
2456
  // we use querySelectorAll because documentFragments don't have getElementsByTagName
2454
- var descendants = element.getElementsByTagName ? element.getElementsByTagName('*') :
2457
+ var descendants = element.getElementsByTagName ? sliceArgs(element.getElementsByTagName('*')) :
2455
2458
  element.querySelectorAll ? element.querySelectorAll('*') : [];
2456
2459
  for (var i = 0, l = descendants.length; i < l; i++) {
2457
2460
  jqLiteRemoveData(descendants[i]);
@@ -3150,26 +3153,37 @@ forEach({
3150
3153
 
3151
3154
  clone: jqLiteClone,
3152
3155
 
3153
- triggerHandler: function(element, eventName, eventData) {
3154
- // Copy event handlers in case event handlers array is modified during execution.
3155
- var eventFns = (jqLiteExpandoStore(element, 'events') || {})[eventName],
3156
- eventFnsCopy = shallowCopy(eventFns || []);
3156
+ triggerHandler: function(element, event, extraParameters) {
3157
3157
 
3158
- eventData = eventData || [];
3158
+ var dummyEvent, eventFnsCopy, handlerArgs;
3159
+ var eventName = event.type || event;
3160
+ var eventFns = (jqLiteExpandoStore(element, 'events') || {})[eventName];
3159
3161
 
3160
- var event = [{
3161
- preventDefault: function() {
3162
- this.defaultPrevented = true;
3163
- },
3164
- isDefaultPrevented: function() {
3165
- return this.defaultPrevented === true;
3166
- },
3167
- stopPropagation: noop
3168
- }];
3162
+ if (eventFns) {
3169
3163
 
3170
- forEach(eventFnsCopy, function(fn) {
3171
- fn.apply(element, event.concat(eventData));
3172
- });
3164
+ // Create a dummy event to pass to the handlers
3165
+ dummyEvent = {
3166
+ preventDefault: function() { this.defaultPrevented = true; },
3167
+ isDefaultPrevented: function() { return this.defaultPrevented === true; },
3168
+ stopPropagation: noop,
3169
+ type: eventName,
3170
+ target: element
3171
+ };
3172
+
3173
+ // If a custom event was provided then extend our dummy event with it
3174
+ if (event.type) {
3175
+ dummyEvent = extend(dummyEvent, event);
3176
+ }
3177
+
3178
+ // Copy event handlers in case event handlers array is modified during execution.
3179
+ eventFnsCopy = shallowCopy(eventFns);
3180
+ handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];
3181
+
3182
+ forEach(eventFnsCopy, function(fn) {
3183
+ fn.apply(element, handlerArgs);
3184
+ });
3185
+
3186
+ }
3173
3187
  }
3174
3188
  }, function(fn, name){
3175
3189
  /**
@@ -5345,7 +5359,7 @@ function $TemplateCacheProvider() {
5345
5359
  * The directive definition object provides instructions to the {@link ng.$compile
5346
5360
  * compiler}. The attributes are:
5347
5361
  *
5348
- * ### `multiElement`
5362
+ * #### `multiElement`
5349
5363
  * When this property is set to true, the HTML compiler will collect DOM nodes between
5350
5364
  * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them
5351
5365
  * together as the directive elements. It is recomended that this feature be used on directives
@@ -5468,7 +5482,7 @@ function $TemplateCacheProvider() {
5468
5482
  *
5469
5483
  * #### `template`
5470
5484
  * HTML markup that may:
5471
- * * Replace the contents of the directive's element (defualt).
5485
+ * * Replace the contents of the directive's element (default).
5472
5486
  * * Replace the directive's element itself (if `replace` is true - DEPRECATED).
5473
5487
  * * Wrap the contents of the directive's element (if `transclude` is true).
5474
5488
  *
@@ -6741,7 +6755,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6741
6755
  if (parentGet.literal) {
6742
6756
  compare = equals;
6743
6757
  } else {
6744
- compare = function(a,b) { return a === b; };
6758
+ compare = function(a,b) { return a === b || (a !== a && b !== b); };
6745
6759
  }
6746
6760
  parentSet = parentGet.assign || function() {
6747
6761
  // reset the change, or we will throw this exception on every $digest
@@ -7265,7 +7279,25 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7265
7279
  }
7266
7280
  var fragment = document.createDocumentFragment();
7267
7281
  fragment.appendChild(firstElementToRemove);
7268
- newNode[jqLite.expando] = firstElementToRemove[jqLite.expando];
7282
+
7283
+ // Copy over user data (that includes Angular's $scope etc.). Don't copy private
7284
+ // data here because there's no public interface in jQuery to do that and copying over
7285
+ // event listeners (which is the main use of private data) wouldn't work anyway.
7286
+ jqLite(newNode).data(jqLite(firstElementToRemove).data());
7287
+
7288
+ // Remove data of the replaced element. We cannot just call .remove()
7289
+ // on the element it since that would deallocate scope that is needed
7290
+ // for the new node. Instead, remove the data "manually".
7291
+ if (!jQuery) {
7292
+ delete jqLite.cache[firstElementToRemove[jqLite.expando]];
7293
+ } else {
7294
+ // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after the replaced
7295
+ // element. Note that we need to use the original method here and not the one monkey-patched by Angular
7296
+ // since the patched method emits the $destroy event causing the scope to be trashed and we do need
7297
+ // the very same scope to work with the new element.
7298
+ jQuery.cleanData.$$original([firstElementToRemove]);
7299
+ }
7300
+
7269
7301
  for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {
7270
7302
  var element = elementsToRemove[k];
7271
7303
  jqLite(element).remove(); // must do this way to clean up expando
@@ -7793,6 +7825,7 @@ function $HttpProvider() {
7793
7825
  * - {@link ng.$http#put $http.put}
7794
7826
  * - {@link ng.$http#delete $http.delete}
7795
7827
  * - {@link ng.$http#jsonp $http.jsonp}
7828
+ * - {@link ng.$http#patch $http.patch}
7796
7829
  *
7797
7830
  *
7798
7831
  * # Setting HTTP Headers
@@ -8049,7 +8082,7 @@ function $HttpProvider() {
8049
8082
  * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
8050
8083
  * that should abort the request when resolved.
8051
8084
  * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the
8052
- * XHR object. See [requests with credentials]https://developer.mozilla.org/en/http_access_control#section_5
8085
+ * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)
8053
8086
  * for more information.
8054
8087
  * - **responseType** - `{string}` - see
8055
8088
  * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).
@@ -8431,7 +8464,8 @@ function $HttpProvider() {
8431
8464
  promise.then(removePendingReq, removePendingReq);
8432
8465
 
8433
8466
 
8434
- if ((config.cache || defaults.cache) && config.cache !== false && config.method == 'GET') {
8467
+ if ((config.cache || defaults.cache) && config.cache !== false &&
8468
+ (config.method === 'GET' || config.method === 'JSONP')) {
8435
8469
  cache = isObject(config.cache) ? config.cache
8436
8470
  : isObject(defaults.cache) ? defaults.cache
8437
8471
  : defaultCache;
@@ -10002,6 +10036,8 @@ function $LocationProvider(){
10002
10036
  $location = new LocationMode(appBase, '#' + hashPrefix);
10003
10037
  $location.$$parse($location.$$rewrite(initialUrl));
10004
10038
 
10039
+ var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i;
10040
+
10005
10041
  $rootElement.on('click', function(event) {
10006
10042
  // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
10007
10043
  // currently we open nice url link and redirect then
@@ -10024,6 +10060,9 @@ function $LocationProvider(){
10024
10060
  absHref = urlResolve(absHref.animVal).href;
10025
10061
  }
10026
10062
 
10063
+ // Ignore when url is started with javascript: or mailto:
10064
+ if (IGNORE_URI_REGEXP.test(absHref)) return;
10065
+
10027
10066
  // Make relative links work in HTML5 mode for legacy browsers (or at least IE8 & 9)
10028
10067
  // The href should be a regular url e.g. /link/somewhere or link/somewhere or ../somewhere or
10029
10068
  // somewhere#anchor or http://example.com/somewhere
@@ -10878,9 +10917,9 @@ Parser.prototype = {
10878
10917
  var middle;
10879
10918
  var token;
10880
10919
  if ((token = this.expect('?'))) {
10881
- middle = this.ternary();
10920
+ middle = this.assignment();
10882
10921
  if ((token = this.expect(':'))) {
10883
- return this.ternaryFn(left, middle, this.ternary());
10922
+ return this.ternaryFn(left, middle, this.assignment());
10884
10923
  } else {
10885
10924
  this.throwError('expected :', token);
10886
10925
  }
@@ -10968,7 +11007,9 @@ Parser.prototype = {
10968
11007
  return getter(self || object(scope, locals));
10969
11008
  }, {
10970
11009
  assign: function(scope, value, locals) {
10971
- return setter(object(scope, locals), field, value, parser.text);
11010
+ var o = object(scope, locals);
11011
+ if (!o) object.assign(scope, o = {});
11012
+ return setter(o, field, value, parser.text);
10972
11013
  }
10973
11014
  });
10974
11015
  },
@@ -10990,10 +11031,11 @@ Parser.prototype = {
10990
11031
  return v;
10991
11032
  }, {
10992
11033
  assign: function(self, value, locals) {
10993
- var key = indexFn(self, locals);
11034
+ var key = ensureSafeMemberName(indexFn(self, locals), parser.text);
10994
11035
  // prevent overwriting of Function.constructor which would break ensureSafeObject check
10995
- var safe = ensureSafeObject(obj(self, locals), parser.text);
10996
- return safe[key] = value;
11036
+ var o = ensureSafeObject(obj(self, locals), parser.text);
11037
+ if (!o) obj.assign(self, o = {});
11038
+ return o[key] = value;
10997
11039
  }
10998
11040
  });
10999
11041
  },
@@ -11298,8 +11340,12 @@ function $ParseProvider() {
11298
11340
  var parser = new Parser(lexer, $filter, $parseOptions);
11299
11341
  parsedExpression = parser.parse(exp);
11300
11342
 
11301
- if (parsedExpression.constant) parsedExpression.$$watchDelegate = constantWatch;
11302
- else if (oneTime) parsedExpression.$$watchDelegate = oneTimeWatch;
11343
+ if (parsedExpression.constant) {
11344
+ parsedExpression.$$watchDelegate = constantWatch;
11345
+ } else if (oneTime) {
11346
+ parsedExpression.$$watchDelegate = parsedExpression.literal ?
11347
+ oneTimeLiteralWatch : oneTimeWatch;
11348
+ }
11303
11349
 
11304
11350
  if (cacheKey !== 'hasOwnProperty') {
11305
11351
  // Only cache the value if it's not going to mess up the cache object
@@ -11336,6 +11382,30 @@ function $ParseProvider() {
11336
11382
  }, objectEquality, deregisterNotifier);
11337
11383
  }
11338
11384
 
11385
+ function oneTimeLiteralWatch(scope, listener, objectEquality, deregisterNotifier, parsedExpression) {
11386
+ var unwatch;
11387
+ return unwatch = scope.$watch(function oneTimeWatch(scope) {
11388
+ return parsedExpression(scope);
11389
+ }, function oneTimeListener(value, old, scope) {
11390
+ if (isFunction(listener)) {
11391
+ listener.call(this, value, old, scope);
11392
+ }
11393
+ if (isAllDefined(value)) {
11394
+ scope.$$postDigest(function () {
11395
+ if(isAllDefined(value)) unwatch();
11396
+ });
11397
+ }
11398
+ }, objectEquality);
11399
+
11400
+ function isAllDefined(value) {
11401
+ var allDefined = true;
11402
+ forEach(value, function (val) {
11403
+ if (!isDefined(val)) allDefined = false;
11404
+ });
11405
+ return allDefined;
11406
+ }
11407
+ }
11408
+
11339
11409
  function constantWatch(scope, listener, objectEquality, deregisterNotifier, parsedExpression) {
11340
11410
  var unwatch;
11341
11411
  return unwatch = scope.$watch(function constantWatch(scope) {
@@ -11613,143 +11683,122 @@ function qFactory(nextTick, exceptionHandler) {
11613
11683
  * @returns {Deferred} Returns a new instance of deferred.
11614
11684
  */
11615
11685
  var defer = function() {
11616
- var pending = [],
11617
- value, deferred;
11618
-
11619
- deferred = {
11620
-
11621
- resolve: function(val) {
11622
- if (pending) {
11623
- var callbacks = pending;
11624
- pending = undefined;
11625
- value = ref(val);
11626
-
11627
- if (callbacks.length) {
11628
- nextTick(function() {
11629
- var callback;
11630
- for (var i = 0, ii = callbacks.length; i < ii; i++) {
11631
- callback = callbacks[i];
11632
- value.then(callback[0], callback[1], callback[2]);
11633
- }
11634
- });
11635
- }
11636
- }
11637
- },
11638
-
11639
-
11640
- reject: function(reason) {
11641
- deferred.resolve(createInternalRejectedPromise(reason));
11642
- },
11686
+ return new Deferred();
11687
+ };
11643
11688
 
11689
+ function Promise () {
11690
+ this.$$pending = [];
11691
+ }
11644
11692
 
11645
- notify: function(progress) {
11646
- if (pending) {
11647
- var callbacks = pending;
11693
+ Promise.prototype = {
11694
+ then: function(callback, errback, progressback) {
11695
+ var result = new Deferred();
11648
11696
 
11649
- if (pending.length) {
11650
- nextTick(function() {
11651
- var callback;
11652
- for (var i = 0, ii = callbacks.length; i < ii; i++) {
11653
- callback = callbacks[i];
11654
- callback[2](progress);
11655
- }
11656
- });
11657
- }
11697
+ var wrappedCallback = function(value) {
11698
+ try {
11699
+ result.resolve((isFunction(callback) ? callback : defaultCallback)(value));
11700
+ } catch(e) {
11701
+ result.reject(e);
11702
+ exceptionHandler(e);
11658
11703
  }
11659
- },
11660
-
11661
-
11662
- promise: {
11663
- then: function(callback, errback, progressback) {
11664
- var result = defer();
11665
-
11666
- var wrappedCallback = function(value) {
11667
- try {
11668
- result.resolve((isFunction(callback) ? callback : defaultCallback)(value));
11669
- } catch(e) {
11670
- result.reject(e);
11671
- exceptionHandler(e);
11672
- }
11673
- };
11704
+ };
11674
11705
 
11675
- var wrappedErrback = function(reason) {
11676
- try {
11677
- result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
11678
- } catch(e) {
11679
- result.reject(e);
11680
- exceptionHandler(e);
11681
- }
11682
- };
11706
+ var wrappedErrback = function(reason) {
11707
+ try {
11708
+ result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
11709
+ } catch(e) {
11710
+ result.reject(e);
11711
+ exceptionHandler(e);
11712
+ }
11713
+ };
11683
11714
 
11684
- var wrappedProgressback = function(progress) {
11685
- try {
11686
- result.notify((isFunction(progressback) ? progressback : defaultCallback)(progress));
11687
- } catch(e) {
11688
- exceptionHandler(e);
11689
- }
11690
- };
11715
+ var wrappedProgressback = function(progress) {
11716
+ try {
11717
+ result.notify((isFunction(progressback) ? progressback : defaultCallback)(progress));
11718
+ } catch(e) {
11719
+ exceptionHandler(e);
11720
+ }
11721
+ };
11691
11722
 
11692
- if (pending) {
11693
- pending.push([wrappedCallback, wrappedErrback, wrappedProgressback]);
11694
- } else {
11695
- value.then(wrappedCallback, wrappedErrback, wrappedProgressback);
11696
- }
11723
+ if (this.$$pending) {
11724
+ this.$$pending.push([wrappedCallback, wrappedErrback, wrappedProgressback]);
11725
+ } else {
11726
+ this.$$value.then(wrappedCallback, wrappedErrback, wrappedProgressback);
11727
+ }
11697
11728
 
11698
- return result.promise;
11699
- },
11729
+ return result.promise;
11730
+ },
11700
11731
 
11701
- "catch": function(callback) {
11702
- return this.then(null, callback);
11703
- },
11732
+ "catch": function(callback) {
11733
+ return this.then(null, callback);
11734
+ },
11735
+ "finally": function(callback) {
11736
+ return this.then(function(value) {
11737
+ return handleCallback(value, true, callback);
11738
+ }, function(error) {
11739
+ return handleCallback(error, false, callback);
11740
+ });
11741
+ }
11742
+ };
11704
11743
 
11705
- "finally": function(callback) {
11744
+ //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native
11745
+ function simpleBind(context, fn) {
11746
+ return function(value) {
11747
+ fn.call(context, value);
11748
+ };
11749
+ }
11706
11750
 
11707
- function makePromise(value, resolved) {
11708
- var result = defer();
11709
- if (resolved) {
11710
- result.resolve(value);
11711
- } else {
11712
- result.reject(value);
11713
- }
11714
- return result.promise;
11715
- }
11751
+ function Deferred () {
11752
+ this.promise = new Promise();
11753
+ //Necessary to support unbound execution :/
11754
+ this.resolve = simpleBind(this, this.resolve);
11755
+ this.reject = simpleBind(this, this.reject);
11756
+ this.notify = simpleBind(this, this.notify);
11757
+ }
11716
11758
 
11717
- function handleCallback(value, isResolved) {
11718
- var callbackOutput = null;
11719
- try {
11720
- callbackOutput = (callback ||defaultCallback)();
11721
- } catch(e) {
11722
- return makePromise(e, false);
11759
+ Deferred.prototype = {
11760
+ resolve: function(val) {
11761
+ if (this.promise.$$pending) {
11762
+ var callbacks = this.promise.$$pending;
11763
+ this.promise.$$pending = undefined;
11764
+ this.promise.$$value = ref(val);
11765
+
11766
+ if (callbacks.length) {
11767
+ nextTick(simpleBind(this, function() {
11768
+ var callback;
11769
+ for (var i = 0, ii = callbacks.length; i < ii; i++) {
11770
+ callback = callbacks[i];
11771
+ this.promise.$$value.then(callback[0], callback[1], callback[2]);
11723
11772
  }
11724
- if (isPromiseLike(callbackOutput)) {
11725
- return callbackOutput.then(function() {
11726
- return makePromise(value, isResolved);
11727
- }, function(error) {
11728
- return makePromise(error, false);
11729
- });
11730
- } else {
11731
- return makePromise(value, isResolved);
11773
+ }));
11774
+ }
11775
+ }
11776
+ },
11777
+ reject: function(reason) {
11778
+ this.resolve(createInternalRejectedPromise(reason));
11779
+ },
11780
+ notify: function(progress) {
11781
+ if (this.promise.$$pending) {
11782
+ var callbacks = this.promise.$$pending;
11783
+
11784
+ if (this.promise.$$pending.length) {
11785
+ nextTick(function() {
11786
+ var callback;
11787
+ for (var i = 0, ii = callbacks.length; i < ii; i++) {
11788
+ callback = callbacks[i];
11789
+ callback[2](progress);
11732
11790
  }
11733
- }
11734
-
11735
- return this.then(function(value) {
11736
- return handleCallback(value, true);
11737
- }, function(error) {
11738
- return handleCallback(error, false);
11739
11791
  });
11740
11792
  }
11741
11793
  }
11742
- };
11743
-
11744
- return deferred;
11794
+ }
11745
11795
  };
11746
11796
 
11747
-
11748
11797
  var ref = function(value) {
11749
11798
  if (isPromiseLike(value)) return value;
11750
11799
  return {
11751
11800
  then: function(callback) {
11752
- var result = defer();
11801
+ var result = new Deferred();
11753
11802
  nextTick(function() {
11754
11803
  result.resolve(callback(value));
11755
11804
  });
@@ -11796,15 +11845,43 @@ function qFactory(nextTick, exceptionHandler) {
11796
11845
  * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.
11797
11846
  */
11798
11847
  var reject = function(reason) {
11799
- var result = defer();
11848
+ var result = new Deferred();
11800
11849
  result.reject(reason);
11801
11850
  return result.promise;
11802
11851
  };
11803
11852
 
11853
+ var makePromise = function makePromise(value, resolved) {
11854
+ var result = new Deferred();
11855
+ if (resolved) {
11856
+ result.resolve(value);
11857
+ } else {
11858
+ result.reject(value);
11859
+ }
11860
+ return result.promise;
11861
+ };
11862
+
11863
+ var handleCallback = function handleCallback(value, isResolved, callback) {
11864
+ var callbackOutput = null;
11865
+ try {
11866
+ callbackOutput = (callback ||defaultCallback)();
11867
+ } catch(e) {
11868
+ return makePromise(e, false);
11869
+ }
11870
+ if (isPromiseLike(callbackOutput)) {
11871
+ return callbackOutput.then(function() {
11872
+ return makePromise(value, isResolved);
11873
+ }, function(error) {
11874
+ return makePromise(error, false);
11875
+ });
11876
+ } else {
11877
+ return makePromise(value, isResolved);
11878
+ }
11879
+ };
11880
+
11804
11881
  var createInternalRejectedPromise = function(reason) {
11805
11882
  return {
11806
11883
  then: function(callback, errback) {
11807
- var result = defer();
11884
+ var result = new Deferred();
11808
11885
  nextTick(function() {
11809
11886
  try {
11810
11887
  result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
@@ -11833,7 +11910,7 @@ function qFactory(nextTick, exceptionHandler) {
11833
11910
  * @returns {Promise} Returns a promise of the passed value or promise
11834
11911
  */
11835
11912
  var when = function(value, callback, errback, progressback) {
11836
- var result = defer(),
11913
+ var result = new Deferred(),
11837
11914
  done;
11838
11915
 
11839
11916
  var wrappedCallback = function(value) {
@@ -11907,7 +11984,7 @@ function qFactory(nextTick, exceptionHandler) {
11907
11984
  * with the same rejection value.
11908
11985
  */
11909
11986
  function all(promises) {
11910
- var deferred = defer(),
11987
+ var deferred = new Deferred(),
11911
11988
  counter = 0,
11912
11989
  results = isArray(promises) ? [] : {};
11913
11990
 
@@ -11941,7 +12018,7 @@ function qFactory(nextTick, exceptionHandler) {
11941
12018
  return new Q(resolver);
11942
12019
  }
11943
12020
 
11944
- var deferred = defer();
12021
+ var deferred = new Deferred();
11945
12022
 
11946
12023
  function resolveFn(value) {
11947
12024
  deferred.resolve(value);
@@ -12244,7 +12321,6 @@ function $RootScopeProvider(){
12244
12321
  * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the
12245
12322
  * listener was called due to initialization.
12246
12323
  *
12247
- * The example below contains an illustration of using a function as your $watch listener
12248
12324
  *
12249
12325
  *
12250
12326
  * # Example
@@ -12274,14 +12350,14 @@ function $RootScopeProvider(){
12274
12350
 
12275
12351
 
12276
12352
 
12277
- // Using a listener function
12353
+ // Using a function as a watchExpression
12278
12354
  var food;
12279
12355
  scope.foodCounter = 0;
12280
12356
  expect(scope.foodCounter).toEqual(0);
12281
12357
  scope.$watch(
12282
- // This is the listener function
12358
+ // This function returns the value being watched. It is called for each turn of the $digest loop
12283
12359
  function() { return food; },
12284
- // This is the change handler
12360
+ // This is the change listener, called when the value returned from the above function changes
12285
12361
  function(newValue, oldValue) {
12286
12362
  if ( newValue !== oldValue ) {
12287
12363
  // Only increment the counter if the value changed
@@ -15407,7 +15483,7 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d
15407
15483
  * (e.g. `"h 'o''clock'"`).
15408
15484
  *
15409
15485
  * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
15410
- * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and its
15486
+ * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its
15411
15487
  * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
15412
15488
  * specified in the string input, the time is considered to be in the local timezone.
15413
15489
  * @param {string=} format Formatting rules (see Description). If not specified,
@@ -15923,12 +15999,12 @@ var htmlAnchorDirective = valueFn({
15923
15999
  *
15924
16000
  * The wrong way to write it:
15925
16001
  * ```html
15926
- * <a href="http://www.gravatar.com/avatar/{{hash}}"/>
16002
+ * <a href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
15927
16003
  * ```
15928
16004
  *
15929
16005
  * The correct way to write it:
15930
16006
  * ```html
15931
- * <a ng-href="http://www.gravatar.com/avatar/{{hash}}"/>
16007
+ * <a ng-href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
15932
16008
  * ```
15933
16009
  *
15934
16010
  * @element A
@@ -16330,14 +16406,16 @@ forEach(['src', 'srcset', 'href'], function(attrName) {
16330
16406
  };
16331
16407
  });
16332
16408
 
16333
- /* global -nullFormCtrl */
16409
+ /* global -nullFormCtrl, -SUBMITTED_CLASS */
16334
16410
  var nullFormCtrl = {
16335
16411
  $addControl: noop,
16336
16412
  $removeControl: noop,
16337
16413
  $setValidity: noop,
16338
16414
  $setDirty: noop,
16339
- $setPristine: noop
16340
- };
16415
+ $setPristine: noop,
16416
+ $setSubmitted: noop
16417
+ },
16418
+ SUBMITTED_CLASS = 'ng-submitted';
16341
16419
 
16342
16420
  /**
16343
16421
  * @ngdoc type
@@ -16390,6 +16468,7 @@ function FormController(element, attrs, $scope, $animate) {
16390
16468
  form.$pristine = true;
16391
16469
  form.$valid = true;
16392
16470
  form.$invalid = false;
16471
+ form.$submitted = false;
16393
16472
 
16394
16473
  parentForm.$addControl(form);
16395
16474
 
@@ -16558,16 +16637,28 @@ function FormController(element, attrs, $scope, $animate) {
16558
16637
  * saving or resetting it.
16559
16638
  */
16560
16639
  form.$setPristine = function () {
16561
- $animate.removeClass(element, DIRTY_CLASS);
16562
- $animate.addClass(element, PRISTINE_CLASS);
16640
+ $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);
16563
16641
  form.$dirty = false;
16564
16642
  form.$pristine = true;
16643
+ form.$submitted = false;
16565
16644
  forEach(controls, function(control) {
16566
16645
  control.$setPristine();
16567
16646
  });
16568
16647
  };
16569
- }
16570
16648
 
16649
+ /**
16650
+ * @ngdoc method
16651
+ * @name form.FormController#setSubmitted
16652
+ *
16653
+ * @description
16654
+ * Sets the form to its submitted state.
16655
+ */
16656
+ form.$setSubmitted = function () {
16657
+ $animate.addClass(element, SUBMITTED_CLASS);
16658
+ form.$submitted = true;
16659
+ parentForm.$setSubmitted();
16660
+ };
16661
+ }
16571
16662
 
16572
16663
  /**
16573
16664
  * @ngdoc directive
@@ -16617,6 +16708,7 @@ function FormController(element, attrs, $scope, $animate) {
16617
16708
  * - `ng-invalid` is set if the form is invalid.
16618
16709
  * - `ng-pristine` is set if the form is pristine.
16619
16710
  * - `ng-dirty` is set if the form is dirty.
16711
+ * - `ng-submitted` is set if the form was submitted.
16620
16712
  *
16621
16713
  * Keep in mind that ngAnimate can detect each of these classes when added and removed.
16622
16714
  *
@@ -16753,6 +16845,7 @@ var formDirectiveFactory = function(isNgForm) {
16753
16845
  var handleFormSubmission = function(event) {
16754
16846
  scope.$apply(function() {
16755
16847
  controller.$commitViewValue();
16848
+ controller.$setSubmitted();
16756
16849
  });
16757
16850
 
16758
16851
  event.preventDefault
@@ -16930,7 +17023,7 @@ var inputType = {
16930
17023
  }]);
16931
17024
  </script>
16932
17025
  <form name="myForm" ng-controller="DateController as dateCtrl">
16933
- Pick a date between in 2013:
17026
+ Pick a date in 2013:
16934
17027
  <input type="date" id="exampleInput" name="input" ng-model="value"
16935
17028
  placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required />
16936
17029
  <span class="error" ng-show="myForm.input.$error.required">
@@ -18980,6 +19073,8 @@ var ngModelDirective = function() {
18980
19073
  }
18981
19074
 
18982
19075
  element.on('blur', function(ev) {
19076
+ if (modelCtrl.$touched) return;
19077
+
18983
19078
  scope.$apply(function() {
18984
19079
  modelCtrl.$setTouched();
18985
19080
  });
@@ -18999,7 +19094,15 @@ var ngModelDirective = function() {
18999
19094
  * The expression is evaluated immediately, unlike the JavaScript onchange event
19000
19095
  * which only triggers at the end of a change (usually, when the user leaves the
19001
19096
  * form element or presses the return key).
19002
- * The expression is not evaluated when the value change is coming from the model.
19097
+ *
19098
+ * The `ngChange` expression is only evaluated when a change in the input value causes
19099
+ * a new value to be committed to the model.
19100
+ *
19101
+ * It will not be evaluated:
19102
+ * * if the value returned from the `$parsers` transformation pipeline has not changed
19103
+ * * if the input has continued to be invalid since the model will stay `null`
19104
+ * * if the model is changed programmatically and not by a change to the input value
19105
+ *
19003
19106
  *
19004
19107
  * Note, this directive requires `ngModel` to be present.
19005
19108
  *
@@ -20156,10 +20259,16 @@ var ngCloakDirective = ngDirective({
20156
20259
  *
20157
20260
  * @element ANY
20158
20261
  * @scope
20159
- * @param {expression} ngController Name of a globally accessible constructor function or an
20160
- * {@link guide/expression expression} that on the current scope evaluates to a
20161
- * constructor function. The controller instance can be published into a scope property
20162
- * by specifying `as propertyName`.
20262
+ * @param {expression} ngController Name of a constructor function registered with the current
20263
+ * {@link ng.$controllerProvider $controllerProvider} or an {@link guide/expression expression}
20264
+ * that on the current scope evaluates to a constructor function.
20265
+ *
20266
+ * The controller instance can be published into a scope property by specifying
20267
+ * `ng-controller="as propertyName"`.
20268
+ *
20269
+ * If the current `$controllerProvider` is configured to use globals (via
20270
+ * {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may
20271
+ * also be the name of a globally accessible constructor function (not recommended).
20163
20272
  *
20164
20273
  * @example
20165
20274
  * Here is a simple form for editing user contact information. Adding, removing, clearing, and
@@ -20724,6 +20833,13 @@ forEach(
20724
20833
  * server and reloading the current page), but only if the form does not contain `action`,
20725
20834
  * `data-action`, or `x-action` attributes.
20726
20835
  *
20836
+ * <div class="alert alert-warning">
20837
+ * **Warning:** Be careful not to cause "double-submission" by using both the `ngClick` and
20838
+ * `ngSubmit` handlers together. See the
20839
+ * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation}
20840
+ * for a detailed discussion of when `ngSubmit` may be triggered.
20841
+ * </div>
20842
+ *
20727
20843
  * @element form
20728
20844
  * @priority 0
20729
20845
  * @param {expression} ngSubmit {@link guide/expression Expression} to eval.
@@ -23091,21 +23207,37 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
23091
23207
  value = valueFn(scope, locals);
23092
23208
  }
23093
23209
  }
23094
- // Update the null option's selected property here so $render cleans it up correctly
23095
- if (optionGroupsCache[0].length > 1) {
23096
- if (optionGroupsCache[0][1].id !== key) {
23097
- optionGroupsCache[0][1].selected = false;
23098
- }
23099
- }
23100
23210
  }
23101
23211
  ctrl.$setViewValue(value);
23212
+ render();
23102
23213
  });
23103
23214
  });
23104
23215
 
23105
23216
  ctrl.$render = render;
23106
23217
 
23107
- // TODO(vojta): can't we optimize this ?
23108
- scope.$watch(render);
23218
+ scope.$watchCollection(valuesFn, render);
23219
+ if ( multiple ) {
23220
+ scope.$watchCollection(function() { return ctrl.$modelValue; }, render);
23221
+ }
23222
+
23223
+ function getSelectedSet() {
23224
+ var selectedSet = false;
23225
+ if (multiple) {
23226
+ var modelValue = ctrl.$modelValue;
23227
+ if (trackFn && isArray(modelValue)) {
23228
+ selectedSet = new HashMap([]);
23229
+ var locals = {};
23230
+ for (var trackIndex = 0; trackIndex < modelValue.length; trackIndex++) {
23231
+ locals[valueName] = modelValue[trackIndex];
23232
+ selectedSet.put(trackFn(scope, locals), modelValue[trackIndex]);
23233
+ }
23234
+ } else {
23235
+ selectedSet = new HashMap(modelValue);
23236
+ }
23237
+ }
23238
+ return selectedSet;
23239
+ }
23240
+
23109
23241
 
23110
23242
  function render() {
23111
23243
  // Temporary location for the option groups before we render them
@@ -23123,22 +23255,11 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
23123
23255
  groupIndex, index,
23124
23256
  locals = {},
23125
23257
  selected,
23126
- selectedSet = false, // nothing is selected yet
23258
+ selectedSet = getSelectedSet(),
23127
23259
  lastElement,
23128
23260
  element,
23129
23261
  label;
23130
23262
 
23131
- if (multiple) {
23132
- if (trackFn && isArray(modelValue)) {
23133
- selectedSet = new HashMap([]);
23134
- for (var trackIndex = 0; trackIndex < modelValue.length; trackIndex++) {
23135
- locals[valueName] = modelValue[trackIndex];
23136
- selectedSet.put(trackFn(scope, locals), modelValue[trackIndex]);
23137
- }
23138
- } else {
23139
- selectedSet = new HashMap(modelValue);
23140
- }
23141
- }
23142
23263
 
23143
23264
  // We now build up the list of options we need (we merge later)
23144
23265
  for (index = 0; length = keys.length, index < length; index++) {
@@ -23234,7 +23355,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
23234
23355
  lastElement.val(existingOption.id = option.id);
23235
23356
  }
23236
23357
  // lastElement.prop('selected') provided by jQuery has side-effects
23237
- if (existingOption.selected !== option.selected) {
23358
+ if (lastElement[0].selected !== option.selected) {
23238
23359
  lastElement.prop('selected', (existingOption.selected = option.selected));
23239
23360
  if (msie) {
23240
23361
  // See #7692
@@ -23257,6 +23378,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
23257
23378
  (element = optionTemplate.clone())
23258
23379
  .val(option.id)
23259
23380
  .prop('selected', option.selected)
23381
+ .attr('selected', option.selected)
23260
23382
  .text(option.label);
23261
23383
  }
23262
23384