angularjs-rails 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.4.0
2
+ * @license AngularJS v1.4.2
3
3
  * (c) 2010-2015 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -105,7 +105,8 @@ ngTouch.factory('$swipe', [function() {
105
105
  * `$swipe` will listen for `mouse` and `touch` events.
106
106
  *
107
107
  * The four events are `start`, `move`, `end`, and `cancel`. `start`, `move`, and `end`
108
- * receive as a parameter a coordinates object of the form `{ x: 150, y: 310 }`.
108
+ * receive as a parameter a coordinates object of the form `{ x: 150, y: 310 }` and the raw
109
+ * `event`. `cancel` receives the raw `event` as its single parameter.
109
110
  *
110
111
  * `start` is called on either `mousedown` or `touchstart`. After this event, `$swipe` is
111
112
  * watching for `touchmove` or `mousemove` events. These events are ignored until the total
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.4.0
2
+ * @license AngularJS v1.4.2
3
3
  * (c) 2010-2015 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -57,7 +57,7 @@ function minErr(module, ErrorConstructor) {
57
57
  return match;
58
58
  });
59
59
 
60
- message += '\nhttp://errors.angularjs.org/1.4.0/' +
60
+ message += '\nhttp://errors.angularjs.org/1.4.2/' +
61
61
  (module ? module + '/' : '') + code;
62
62
 
63
63
  for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
@@ -421,8 +421,12 @@ function baseExtend(dst, objs, deep) {
421
421
  var src = obj[key];
422
422
 
423
423
  if (deep && isObject(src)) {
424
- if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
425
- baseExtend(dst[key], [src], true);
424
+ if (isDate(src)) {
425
+ dst[key] = new Date(src.valueOf());
426
+ } else {
427
+ if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
428
+ baseExtend(dst[key], [src], true);
429
+ }
426
430
  } else {
427
431
  dst[key] = src;
428
432
  }
@@ -533,6 +537,11 @@ identity.$inject = [];
533
537
 
534
538
  function valueFn(value) {return function() {return value;};}
535
539
 
540
+ function hasCustomToString(obj) {
541
+ return isFunction(obj.toString) && obj.toString !== Object.prototype.toString;
542
+ }
543
+
544
+
536
545
  /**
537
546
  * @ngdoc function
538
547
  * @name angular.isUndefined
@@ -864,9 +873,18 @@ function copy(source, destination, stackSource, stackDest) {
864
873
 
865
874
  if (!destination) {
866
875
  destination = source;
867
- if (source) {
876
+ if (isObject(source)) {
877
+ var index;
878
+ if (stackSource && (index = stackSource.indexOf(source)) !== -1) {
879
+ return stackDest[index];
880
+ }
881
+
882
+ // TypedArray, Date and RegExp have specific copy functionality and must be
883
+ // pushed onto the stack before returning.
884
+ // Array and other objects create the base object and recurse to copy child
885
+ // objects. The array/object will be pushed onto the stack when recursed.
868
886
  if (isArray(source)) {
869
- destination = copy(source, [], stackSource, stackDest);
887
+ return copy(source, [], stackSource, stackDest);
870
888
  } else if (isTypedArray(source)) {
871
889
  destination = new source.constructor(source);
872
890
  } else if (isDate(source)) {
@@ -874,9 +892,14 @@ function copy(source, destination, stackSource, stackDest) {
874
892
  } else if (isRegExp(source)) {
875
893
  destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
876
894
  destination.lastIndex = source.lastIndex;
877
- } else if (isObject(source)) {
895
+ } else {
878
896
  var emptyObject = Object.create(getPrototypeOf(source));
879
- destination = copy(source, emptyObject, stackSource, stackDest);
897
+ return copy(source, emptyObject, stackSource, stackDest);
898
+ }
899
+
900
+ if (stackDest) {
901
+ stackSource.push(source);
902
+ stackDest.push(destination);
880
903
  }
881
904
  }
882
905
  } else {
@@ -887,9 +910,6 @@ function copy(source, destination, stackSource, stackDest) {
887
910
  stackDest = stackDest || [];
888
911
 
889
912
  if (isObject(source)) {
890
- var index = stackSource.indexOf(source);
891
- if (index !== -1) return stackDest[index];
892
-
893
913
  stackSource.push(source);
894
914
  stackDest.push(destination);
895
915
  }
@@ -898,12 +918,7 @@ function copy(source, destination, stackSource, stackDest) {
898
918
  if (isArray(source)) {
899
919
  destination.length = 0;
900
920
  for (var i = 0; i < source.length; i++) {
901
- result = copy(source[i], null, stackSource, stackDest);
902
- if (isObject(source[i])) {
903
- stackSource.push(source[i]);
904
- stackDest.push(result);
905
- }
906
- destination.push(result);
921
+ destination.push(copy(source[i], null, stackSource, stackDest));
907
922
  }
908
923
  } else {
909
924
  var h = destination.$$hashKey;
@@ -917,20 +932,20 @@ function copy(source, destination, stackSource, stackDest) {
917
932
  if (isBlankObject(source)) {
918
933
  // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
919
934
  for (key in source) {
920
- putValue(key, source[key], destination, stackSource, stackDest);
935
+ destination[key] = copy(source[key], null, stackSource, stackDest);
921
936
  }
922
937
  } else if (source && typeof source.hasOwnProperty === 'function') {
923
938
  // Slow path, which must rely on hasOwnProperty
924
939
  for (key in source) {
925
940
  if (source.hasOwnProperty(key)) {
926
- putValue(key, source[key], destination, stackSource, stackDest);
941
+ destination[key] = copy(source[key], null, stackSource, stackDest);
927
942
  }
928
943
  }
929
944
  } else {
930
945
  // Slowest path --- hasOwnProperty can't be called as a method
931
946
  for (key in source) {
932
947
  if (hasOwnProperty.call(source, key)) {
933
- putValue(key, source[key], destination, stackSource, stackDest);
948
+ destination[key] = copy(source[key], null, stackSource, stackDest);
934
949
  }
935
950
  }
936
951
  }
@@ -938,16 +953,6 @@ function copy(source, destination, stackSource, stackDest) {
938
953
  }
939
954
  }
940
955
  return destination;
941
-
942
- function putValue(key, val, destination, stackSource, stackDest) {
943
- // No context allocation, trivial outer scope, easily inlined
944
- var result = copy(val, null, stackSource, stackDest);
945
- if (isObject(val)) {
946
- stackSource.push(val);
947
- stackDest.push(result);
948
- }
949
- destination[key] = result;
950
- }
951
956
  }
952
957
 
953
958
  /**
@@ -2005,7 +2010,7 @@ function setupModuleLoader(window) {
2005
2010
  * @description
2006
2011
  * See {@link auto.$provide#provider $provide.provider()}.
2007
2012
  */
2008
- provider: invokeLater('$provide', 'provider'),
2013
+ provider: invokeLaterAndSetModuleName('$provide', 'provider'),
2009
2014
 
2010
2015
  /**
2011
2016
  * @ngdoc method
@@ -2016,7 +2021,7 @@ function setupModuleLoader(window) {
2016
2021
  * @description
2017
2022
  * See {@link auto.$provide#factory $provide.factory()}.
2018
2023
  */
2019
- factory: invokeLater('$provide', 'factory'),
2024
+ factory: invokeLaterAndSetModuleName('$provide', 'factory'),
2020
2025
 
2021
2026
  /**
2022
2027
  * @ngdoc method
@@ -2027,7 +2032,7 @@ function setupModuleLoader(window) {
2027
2032
  * @description
2028
2033
  * See {@link auto.$provide#service $provide.service()}.
2029
2034
  */
2030
- service: invokeLater('$provide', 'service'),
2035
+ service: invokeLaterAndSetModuleName('$provide', 'service'),
2031
2036
 
2032
2037
  /**
2033
2038
  * @ngdoc method
@@ -2062,7 +2067,7 @@ function setupModuleLoader(window) {
2062
2067
  * @description
2063
2068
  * See {@link auto.$provide#decorator $provide.decorator()}.
2064
2069
  */
2065
- decorator: invokeLater('$provide', 'decorator'),
2070
+ decorator: invokeLaterAndSetModuleName('$provide', 'decorator'),
2066
2071
 
2067
2072
  /**
2068
2073
  * @ngdoc method
@@ -2096,7 +2101,7 @@ function setupModuleLoader(window) {
2096
2101
  * See {@link ng.$animateProvider#register $animateProvider.register()} and
2097
2102
  * {@link ngAnimate ngAnimate module} for more information.
2098
2103
  */
2099
- animation: invokeLater('$animateProvider', 'register'),
2104
+ animation: invokeLaterAndSetModuleName('$animateProvider', 'register'),
2100
2105
 
2101
2106
  /**
2102
2107
  * @ngdoc method
@@ -2114,7 +2119,7 @@ function setupModuleLoader(window) {
2114
2119
  * (`myapp_subsection_filterx`).
2115
2120
  * </div>
2116
2121
  */
2117
- filter: invokeLater('$filterProvider', 'register'),
2122
+ filter: invokeLaterAndSetModuleName('$filterProvider', 'register'),
2118
2123
 
2119
2124
  /**
2120
2125
  * @ngdoc method
@@ -2126,7 +2131,7 @@ function setupModuleLoader(window) {
2126
2131
  * @description
2127
2132
  * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
2128
2133
  */
2129
- controller: invokeLater('$controllerProvider', 'register'),
2134
+ controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'),
2130
2135
 
2131
2136
  /**
2132
2137
  * @ngdoc method
@@ -2139,7 +2144,7 @@ function setupModuleLoader(window) {
2139
2144
  * @description
2140
2145
  * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
2141
2146
  */
2142
- directive: invokeLater('$compileProvider', 'directive'),
2147
+ directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'),
2143
2148
 
2144
2149
  /**
2145
2150
  * @ngdoc method
@@ -2189,6 +2194,19 @@ function setupModuleLoader(window) {
2189
2194
  return moduleInstance;
2190
2195
  };
2191
2196
  }
2197
+
2198
+ /**
2199
+ * @param {string} provider
2200
+ * @param {string} method
2201
+ * @returns {angular.Module}
2202
+ */
2203
+ function invokeLaterAndSetModuleName(provider, method) {
2204
+ return function(recipeName, factoryFunction) {
2205
+ if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name;
2206
+ invokeQueue.push([provider, method, arguments]);
2207
+ return moduleInstance;
2208
+ };
2209
+ }
2192
2210
  });
2193
2211
  };
2194
2212
  });
@@ -2332,11 +2350,11 @@ function toDebugString(obj) {
2332
2350
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
2333
2351
  */
2334
2352
  var version = {
2335
- full: '1.4.0', // all of these placeholder strings will be replaced by grunt's
2353
+ full: '1.4.2', // all of these placeholder strings will be replaced by grunt's
2336
2354
  major: 1, // package task
2337
2355
  minor: 4,
2338
- dot: 0,
2339
- codeName: 'jaracimrman-existence'
2356
+ dot: 2,
2357
+ codeName: 'nebular-readjustment'
2340
2358
  };
2341
2359
 
2342
2360
 
@@ -2662,6 +2680,13 @@ function jqLiteAcceptsData(node) {
2662
2680
  return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;
2663
2681
  }
2664
2682
 
2683
+ function jqLiteHasData(node) {
2684
+ for (var key in jqCache[node.ng339]) {
2685
+ return true;
2686
+ }
2687
+ return false;
2688
+ }
2689
+
2665
2690
  function jqLiteBuildFragment(html, context) {
2666
2691
  var tmp, tag, wrap,
2667
2692
  fragment = context.createDocumentFragment(),
@@ -3036,7 +3061,8 @@ function getAliasedAttrName(element, name) {
3036
3061
 
3037
3062
  forEach({
3038
3063
  data: jqLiteData,
3039
- removeData: jqLiteRemoveData
3064
+ removeData: jqLiteRemoveData,
3065
+ hasData: jqLiteHasData
3040
3066
  }, function(fn, name) {
3041
3067
  JQLite[name] = fn;
3042
3068
  });
@@ -4245,7 +4271,7 @@ function createInjector(modulesToLoad, strictDi) {
4245
4271
  }));
4246
4272
 
4247
4273
 
4248
- forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
4274
+ forEach(loadModules(modulesToLoad), function(fn) { if (fn) instanceInjector.invoke(fn); });
4249
4275
 
4250
4276
  return instanceInjector;
4251
4277
 
@@ -5384,7 +5410,7 @@ function Browser(window, document, $log, $sniffer) {
5384
5410
 
5385
5411
  function getHash(url) {
5386
5412
  var index = url.indexOf('#');
5387
- return index === -1 ? '' : url.substr(index + 1);
5413
+ return index === -1 ? '' : url.substr(index);
5388
5414
  }
5389
5415
 
5390
5416
  /**
@@ -5468,7 +5494,7 @@ function Browser(window, document, $log, $sniffer) {
5468
5494
  // Do the assignment again so that those two variables are referentially identical.
5469
5495
  lastHistoryState = cachedState;
5470
5496
  } else {
5471
- if (!sameBase) {
5497
+ if (!sameBase || reloadLocation) {
5472
5498
  reloadLocation = url;
5473
5499
  }
5474
5500
  if (replace) {
@@ -6474,13 +6500,16 @@ function $TemplateCacheProvider() {
6474
6500
  * * `controller` - the directive's required controller instance(s) - Instances are shared
6475
6501
  * among all directives, which allows the directives to use the controllers as a communication
6476
6502
  * channel. The exact value depends on the directive's `require` property:
6503
+ * * no controller(s) required: the directive's own controller, or `undefined` if it doesn't have one
6477
6504
  * * `string`: the controller instance
6478
6505
  * * `array`: array of controller instances
6479
- * * no controller(s) required: `undefined`
6480
6506
  *
6481
6507
  * If a required controller cannot be found, and it is optional, the instance is `null`,
6482
6508
  * otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown.
6483
6509
  *
6510
+ * Note that you can also require the directive's own controller - it will be made available like
6511
+ * like any other controller.
6512
+ *
6484
6513
  * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
6485
6514
  * This is the same as the `$transclude`
6486
6515
  * parameter of directive controllers, see there for details.
@@ -6927,6 +6956,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6927
6956
  if (isObject(bindings.isolateScope)) {
6928
6957
  directive.$$isolateBindings = bindings.isolateScope;
6929
6958
  }
6959
+ directive.$$moduleName = directiveFactory.$$moduleName;
6930
6960
  directives.push(directive);
6931
6961
  } catch (e) {
6932
6962
  $exceptionHandler(e);
@@ -7498,8 +7528,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7498
7528
 
7499
7529
  if (nodeLinkFn.transcludeOnThisElement) {
7500
7530
  childBoundTranscludeFn = createBoundTranscludeFn(
7501
- scope, nodeLinkFn.transclude, parentBoundTranscludeFn,
7502
- nodeLinkFn.elementTranscludeOnThisElement);
7531
+ scope, nodeLinkFn.transclude, parentBoundTranscludeFn);
7503
7532
 
7504
7533
  } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
7505
7534
  childBoundTranscludeFn = parentBoundTranscludeFn;
@@ -7521,7 +7550,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7521
7550
  }
7522
7551
  }
7523
7552
 
7524
- function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn, elementTransclusion) {
7553
+ function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {
7525
7554
 
7526
7555
  var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {
7527
7556
 
@@ -7620,6 +7649,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7620
7649
  }
7621
7650
  break;
7622
7651
  case NODE_TYPE_TEXT: /* Text Node */
7652
+ if (msie === 11) {
7653
+ // Workaround for #11781
7654
+ while (node.parentNode && node.nextSibling && node.nextSibling.nodeType === NODE_TYPE_TEXT) {
7655
+ node.nodeValue = node.nodeValue + node.nextSibling.nodeValue;
7656
+ node.parentNode.removeChild(node.nextSibling);
7657
+ }
7658
+ }
7623
7659
  addTextInterpolateDirective(directives, node.nodeValue);
7624
7660
  break;
7625
7661
  case NODE_TYPE_COMMENT: /* Comment */
@@ -7719,7 +7755,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7719
7755
  previousCompileContext = previousCompileContext || {};
7720
7756
 
7721
7757
  var terminalPriority = -Number.MAX_VALUE,
7722
- newScopeDirective,
7758
+ newScopeDirective = previousCompileContext.newScopeDirective,
7723
7759
  controllerDirectives = previousCompileContext.controllerDirectives,
7724
7760
  newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
7725
7761
  templateDirective = previousCompileContext.templateDirective,
@@ -7885,6 +7921,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7885
7921
  nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
7886
7922
  templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {
7887
7923
  controllerDirectives: controllerDirectives,
7924
+ newScopeDirective: (newScopeDirective !== directive) && newScopeDirective,
7888
7925
  newIsolateScopeDirective: newIsolateScopeDirective,
7889
7926
  templateDirective: templateDirective,
7890
7927
  nonTlbTranscludeDirective: nonTlbTranscludeDirective
@@ -7912,7 +7949,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7912
7949
 
7913
7950
  nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
7914
7951
  nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
7915
- nodeLinkFn.elementTranscludeOnThisElement = hasElementTranscludeDirective;
7916
7952
  nodeLinkFn.templateOnThisElement = hasTemplate;
7917
7953
  nodeLinkFn.transclude = childTranscludeFn;
7918
7954
 
@@ -8073,9 +8109,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
8073
8109
  for (i in elementControllers) {
8074
8110
  controller = elementControllers[i];
8075
8111
  var controllerResult = controller();
8112
+
8076
8113
  if (controllerResult !== controller.instance) {
8114
+ // If the controller constructor has a return value, overwrite the instance
8115
+ // from setupControllers and update the element data
8077
8116
  controller.instance = controllerResult;
8078
- $element.data('$' + directive.name + 'Controller', controllerResult);
8117
+ $element.data('$' + i + 'Controller', controllerResult);
8079
8118
  if (controller === controllerForBindings) {
8080
8119
  // Remove and re-install bindToController bindings
8081
8120
  thisLinkFn.$$destroyBindings();
@@ -8267,7 +8306,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
8267
8306
 
8268
8307
  $compileNode.empty();
8269
8308
 
8270
- $templateRequest($sce.getTrustedResourceUrl(templateUrl))
8309
+ $templateRequest(templateUrl)
8271
8310
  .then(function(content) {
8272
8311
  var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
8273
8312
 
@@ -8375,11 +8414,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
8375
8414
  return a.index - b.index;
8376
8415
  }
8377
8416
 
8378
-
8379
8417
  function assertNoDuplicate(what, previousDirective, directive, element) {
8418
+
8419
+ function wrapModuleNameIfDefined(moduleName) {
8420
+ return moduleName ?
8421
+ (' (module: ' + moduleName + ')') :
8422
+ '';
8423
+ }
8424
+
8380
8425
  if (previousDirective) {
8381
- throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}',
8382
- previousDirective.name, directive.name, what, startingTag(element));
8426
+ throw $compileMinErr('multidir', 'Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}',
8427
+ previousDirective.name, wrapModuleNameIfDefined(previousDirective.$$moduleName),
8428
+ directive.name, wrapModuleNameIfDefined(directive.$$moduleName), what, startingTag(element));
8383
8429
  }
8384
8430
  }
8385
8431
 
@@ -8560,26 +8606,28 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
8560
8606
  var fragment = document.createDocumentFragment();
8561
8607
  fragment.appendChild(firstElementToRemove);
8562
8608
 
8563
- // Copy over user data (that includes Angular's $scope etc.). Don't copy private
8564
- // data here because there's no public interface in jQuery to do that and copying over
8565
- // event listeners (which is the main use of private data) wouldn't work anyway.
8566
- jqLite(newNode).data(jqLite(firstElementToRemove).data());
8567
-
8568
- // Remove data of the replaced element. We cannot just call .remove()
8569
- // on the element it since that would deallocate scope that is needed
8570
- // for the new node. Instead, remove the data "manually".
8571
- if (!jQuery) {
8572
- delete jqLite.cache[firstElementToRemove[jqLite.expando]];
8573
- } else {
8574
- // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after
8575
- // the replaced element. The cleanData version monkey-patched by Angular would cause
8576
- // the scope to be trashed and we do need the very same scope to work with the new
8577
- // element. However, we cannot just cache the non-patched version and use it here as
8578
- // that would break if another library patches the method after Angular does (one
8579
- // example is jQuery UI). Instead, set a flag indicating scope destroying should be
8580
- // skipped this one time.
8581
- skipDestroyOnNextJQueryCleanData = true;
8582
- jQuery.cleanData([firstElementToRemove]);
8609
+ if (jqLite.hasData(firstElementToRemove)) {
8610
+ // Copy over user data (that includes Angular's $scope etc.). Don't copy private
8611
+ // data here because there's no public interface in jQuery to do that and copying over
8612
+ // event listeners (which is the main use of private data) wouldn't work anyway.
8613
+ jqLite(newNode).data(jqLite(firstElementToRemove).data());
8614
+
8615
+ // Remove data of the replaced element. We cannot just call .remove()
8616
+ // on the element it since that would deallocate scope that is needed
8617
+ // for the new node. Instead, remove the data "manually".
8618
+ if (!jQuery) {
8619
+ delete jqLite.cache[firstElementToRemove[jqLite.expando]];
8620
+ } else {
8621
+ // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after
8622
+ // the replaced element. The cleanData version monkey-patched by Angular would cause
8623
+ // the scope to be trashed and we do need the very same scope to work with the new
8624
+ // element. However, we cannot just cache the non-patched version and use it here as
8625
+ // that would break if another library patches the method after Angular does (one
8626
+ // example is jQuery UI). Instead, set a flag indicating scope destroying should be
8627
+ // skipped this one time.
8628
+ skipDestroyOnNextJQueryCleanData = true;
8629
+ jQuery.cleanData([firstElementToRemove]);
8630
+ }
8583
8631
  }
8584
8632
 
8585
8633
  for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {
@@ -8620,9 +8668,19 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
8620
8668
  lastValue,
8621
8669
  parentGet, parentSet, compare;
8622
8670
 
8671
+ if (!hasOwnProperty.call(attrs, attrName)) {
8672
+ // In the case of user defined a binding with the same name as a method in Object.prototype but didn't set
8673
+ // the corresponding attribute. We need to make sure subsequent code won't access to the prototype function
8674
+ attrs[attrName] = undefined;
8675
+ }
8676
+
8623
8677
  switch (mode) {
8624
8678
 
8625
8679
  case '@':
8680
+ if (!attrs[attrName] && !optional) {
8681
+ destination[scopeName] = undefined;
8682
+ }
8683
+
8626
8684
  attrs.$observe(attrName, function(value) {
8627
8685
  destination[scopeName] = value;
8628
8686
  });
@@ -8639,6 +8697,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
8639
8697
  return;
8640
8698
  }
8641
8699
  parentGet = $parse(attrs[attrName]);
8700
+
8642
8701
  if (parentGet.literal) {
8643
8702
  compare = equals;
8644
8703
  } else {
@@ -8677,9 +8736,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
8677
8736
  break;
8678
8737
 
8679
8738
  case '&':
8680
- // Don't assign Object.prototype method to scope
8681
- if (!attrs.hasOwnProperty(attrName) && optional) break;
8682
-
8683
8739
  parentGet = $parse(attrs[attrName]);
8684
8740
 
8685
8741
  // Don't assign noop to destination if expression is not valid
@@ -9080,13 +9136,17 @@ function $HttpParamSerializerProvider() {
9080
9136
  * @name $httpParamSerializer
9081
9137
  * @description
9082
9138
  *
9083
- * Default $http params serializer that converts objects to a part of a request URL
9139
+ * Default {@link $http `$http`} params serializer that converts objects to strings
9084
9140
  * according to the following rules:
9141
+ *
9085
9142
  * * `{'foo': 'bar'}` results in `foo=bar`
9086
9143
  * * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object)
9087
9144
  * * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element)
9088
9145
  * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D"` (stringified and encoded representation of an object)
9146
+ *
9147
+ * Note that serializer will sort the request parameters alphabetically.
9089
9148
  * */
9149
+
9090
9150
  this.$get = function() {
9091
9151
  return function ngParamSerializer(params) {
9092
9152
  if (!params) return '';
@@ -9113,7 +9173,43 @@ function $HttpParamSerializerJQLikeProvider() {
9113
9173
  * @name $httpParamSerializerJQLike
9114
9174
  * @description
9115
9175
  *
9116
- * Alternative $http params serializer that follows jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic.
9176
+ * Alternative {@link $http `$http`} params serializer that follows
9177
+ * jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic.
9178
+ * The serializer will also sort the params alphabetically.
9179
+ *
9180
+ * To use it for serializing `$http` request parameters, set it as the `paramSerializer` property:
9181
+ *
9182
+ * ```js
9183
+ * $http({
9184
+ * url: myUrl,
9185
+ * method: 'GET',
9186
+ * params: myParams,
9187
+ * paramSerializer: '$httpParamSerializerJQLike'
9188
+ * });
9189
+ * ```
9190
+ *
9191
+ * It is also possible to set it as the default `paramSerializer` in the
9192
+ * {@link $httpProvider#defaults `$httpProvider`}.
9193
+ *
9194
+ * Additionally, you can inject the serializer and use it explicitly, for example to serialize
9195
+ * form data for submission:
9196
+ *
9197
+ * ```js
9198
+ * .controller(function($http, $httpParamSerializerJQLike) {
9199
+ * //...
9200
+ *
9201
+ * $http({
9202
+ * url: myUrl,
9203
+ * method: 'POST',
9204
+ * data: $httpParamSerializerJQLike(myData),
9205
+ * headers: {
9206
+ * 'Content-Type': 'application/x-www-form-urlencoded'
9207
+ * }
9208
+ * });
9209
+ *
9210
+ * });
9211
+ * ```
9212
+ *
9117
9213
  * */
9118
9214
  this.$get = function() {
9119
9215
  return function jQueryLikeParamSerializer(params) {
@@ -9270,7 +9366,7 @@ function $HttpProvider() {
9270
9366
  *
9271
9367
  * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`}
9272
9368
  * that will provide the cache for all requests who set their `cache` property to `true`.
9273
- * If you set the `default.cache = false` then only requests that specify their own custom
9369
+ * If you set the `defaults.cache = false` then only requests that specify their own custom
9274
9370
  * cache object will be cached. See {@link $http#caching $http Caching} for more information.
9275
9371
  *
9276
9372
  * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
@@ -9287,10 +9383,11 @@ function $HttpProvider() {
9287
9383
  * - **`defaults.headers.put`**
9288
9384
  * - **`defaults.headers.patch`**
9289
9385
  *
9290
- * - **`defaults.paramSerializer`** - {string|function(Object<string,string>):string} - A function used to prepare string representation
9291
- * of request parameters (specified as an object).
9292
- * If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}.
9293
- * Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}.
9386
+ *
9387
+ * - **`defaults.paramSerializer`** - `{string|function(Object<string,string>):string}` - A function
9388
+ * used to the prepare string representation of request parameters (specified as an object).
9389
+ * If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}.
9390
+ * Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}.
9294
9391
  *
9295
9392
  **/
9296
9393
  var defaults = this.defaults = {
@@ -9756,15 +9853,17 @@ function $HttpProvider() {
9756
9853
  * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,
9757
9854
  * or the per-request config object.
9758
9855
  *
9856
+ * In order to prevent collisions in environments where multiple Angular apps share the
9857
+ * same domain or subdomain, we recommend that each application uses unique cookie name.
9858
+ *
9759
9859
  *
9760
9860
  * @param {object} config Object describing the request to be made and how it should be
9761
9861
  * processed. The object has following properties:
9762
9862
  *
9763
9863
  * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)
9764
9864
  * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.
9765
- * - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned
9766
- * to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be
9767
- * JSONified.
9865
+ * - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be serialized
9866
+ * with the `paramSerializer` and appended as GET parameters.
9768
9867
  * - **data** – `{string|Object}` – Data to be sent as the request message data.
9769
9868
  * - **headers** – `{Object}` – Map of strings or functions which return strings representing
9770
9869
  * HTTP headers to send to the server. If the return value of a function is null, the
@@ -9782,10 +9881,14 @@ function $HttpProvider() {
9782
9881
  * transform function or an array of such functions. The transform function takes the http
9783
9882
  * response body, headers and status and returns its transformed (typically deserialized) version.
9784
9883
  * See {@link ng.$http#overriding-the-default-transformations-per-request
9785
- * Overriding the Default Transformations}
9786
- * - **paramSerializer** - {string|function(Object<string,string>):string} - A function used to prepare string representation
9787
- * of request parameters (specified as an object).
9788
- * Is specified as string, it is interpreted as function registered in with the {$injector}.
9884
+ * Overriding the Default TransformationjqLiks}
9885
+ * - **paramSerializer** - `{string|function(Object<string,string>):string}` - A function used to
9886
+ * prepare the string representation of request parameters (specified as an object).
9887
+ * If specified as string, it is interpreted as function registered with the
9888
+ * {@link $injector $injector}, which means you can create your own serializer
9889
+ * by registering it as a {@link auto.$provide#service service}.
9890
+ * The default serializer is the {@link $httpParamSerializer $httpParamSerializer};
9891
+ * alternatively, you can use the {@link $httpParamSerializerJQLike $httpParamSerializerJQLike}
9789
9892
  * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
9790
9893
  * GET request, otherwise if a cache instance built with
9791
9894
  * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
@@ -9796,7 +9899,7 @@ function $HttpProvider() {
9796
9899
  * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)
9797
9900
  * for more information.
9798
9901
  * - **responseType** - `{string}` - see
9799
- * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).
9902
+ * [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype).
9800
9903
  *
9801
9904
  * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the
9802
9905
  * standard `then` method and two http specific methods: `success` and `error`. The `then`
@@ -11279,7 +11382,7 @@ function LocationHashbangUrl(appBase, hashPrefix) {
11279
11382
  var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
11280
11383
  var withoutHashUrl;
11281
11384
 
11282
- if (withoutBaseUrl.charAt(0) === '#') {
11385
+ if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') {
11283
11386
 
11284
11387
  // The rest of the url starts with a hash so we have
11285
11388
  // got either a hashbang path or a plain hash fragment
@@ -11293,7 +11396,15 @@ function LocationHashbangUrl(appBase, hashPrefix) {
11293
11396
  // There was no hashbang path nor hash fragment:
11294
11397
  // If we are in HTML5 mode we use what is left as the path;
11295
11398
  // Otherwise we ignore what is left
11296
- withoutHashUrl = this.$$html5 ? withoutBaseUrl : '';
11399
+ if (this.$$html5) {
11400
+ withoutHashUrl = withoutBaseUrl;
11401
+ } else {
11402
+ withoutHashUrl = '';
11403
+ if (isUndefined(withoutBaseUrl)) {
11404
+ appBase = url;
11405
+ this.replace();
11406
+ }
11407
+ }
11297
11408
  }
11298
11409
 
11299
11410
  parseAppUrl(withoutHashUrl, this);
@@ -13213,8 +13324,10 @@ ASTCompiler.prototype = {
13213
13324
  nameId.name = ast.property.name;
13214
13325
  }
13215
13326
  }
13216
- recursionFn(intoId);
13327
+ }, function() {
13328
+ self.assign(intoId, 'undefined');
13217
13329
  });
13330
+ recursionFn(intoId);
13218
13331
  }, !!create);
13219
13332
  break;
13220
13333
  case AST.CallExpression:
@@ -13252,8 +13365,10 @@ ASTCompiler.prototype = {
13252
13365
  }
13253
13366
  expression = self.ensureSafeObject(expression);
13254
13367
  self.assign(intoId, expression);
13255
- recursionFn(intoId);
13368
+ }, function() {
13369
+ self.assign(intoId, 'undefined');
13256
13370
  });
13371
+ recursionFn(intoId);
13257
13372
  });
13258
13373
  }
13259
13374
  break;
@@ -14634,6 +14749,19 @@ function qFactory(nextTick, exceptionHandler) {
14634
14749
  return result.promise.then(callback, errback, progressBack);
14635
14750
  };
14636
14751
 
14752
+ /**
14753
+ * @ngdoc method
14754
+ * @name $q#resolve
14755
+ * @kind function
14756
+ *
14757
+ * @description
14758
+ * Alias of {@link ng.$q#when when} to maintain naming consistency with ES6.
14759
+ *
14760
+ * @param {*} value Value or a promise
14761
+ * @returns {Promise} Returns a promise of the passed value or promise
14762
+ */
14763
+ var resolve = when;
14764
+
14637
14765
  /**
14638
14766
  * @ngdoc method
14639
14767
  * @name $q#all
@@ -14702,6 +14830,7 @@ function qFactory(nextTick, exceptionHandler) {
14702
14830
  $Q.defer = defer;
14703
14831
  $Q.reject = reject;
14704
14832
  $Q.when = when;
14833
+ $Q.resolve = resolve;
14705
14834
  $Q.all = all;
14706
14835
 
14707
14836
  return $Q;
@@ -17346,12 +17475,14 @@ var $compileMinErr = minErr('$compile');
17346
17475
  * @name $templateRequest
17347
17476
  *
17348
17477
  * @description
17349
- * The `$templateRequest` service downloads the provided template using `$http` and, upon success,
17350
- * stores the contents inside of `$templateCache`. If the HTTP request fails or the response data
17351
- * of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted
17352
- * by setting the 2nd parameter of the function to true).
17353
- *
17354
- * @param {string} tpl The HTTP request template URL
17478
+ * The `$templateRequest` service runs security checks then downloads the provided template using
17479
+ * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request
17480
+ * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the
17481
+ * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the
17482
+ * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted
17483
+ * when `tpl` is of type string and `$templateCache` has the matching entry.
17484
+ *
17485
+ * @param {string|TrustedResourceUrl} tpl The HTTP request template URL
17355
17486
  * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
17356
17487
  *
17357
17488
  * @return {Promise} a promise for the HTTP response data of the given URL.
@@ -17359,10 +17490,19 @@ var $compileMinErr = minErr('$compile');
17359
17490
  * @property {number} totalPendingRequests total amount of pending template requests being downloaded.
17360
17491
  */
17361
17492
  function $TemplateRequestProvider() {
17362
- this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) {
17493
+ this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) {
17363
17494
  function handleRequestFn(tpl, ignoreRequestError) {
17364
17495
  handleRequestFn.totalPendingRequests++;
17365
17496
 
17497
+ // We consider the template cache holds only trusted templates, so
17498
+ // there's no need to go through whitelisting again for keys that already
17499
+ // are included in there. This also makes Angular accept any script
17500
+ // directive, no matter its name. However, we still need to unwrap trusted
17501
+ // types.
17502
+ if (!isString(tpl) || !$templateCache.get(tpl)) {
17503
+ tpl = $sce.getTrustedResourceUrl(tpl);
17504
+ }
17505
+
17366
17506
  var transformResponse = $http.defaults && $http.defaults.transformResponse;
17367
17507
 
17368
17508
  if (isArray(transformResponse)) {
@@ -18011,9 +18151,11 @@ function $FilterProvider($provide) {
18011
18151
  * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but
18012
18152
  * **will** be matched by `{$: 'John'}`.
18013
18153
  *
18014
- * - `function(value, index)`: A predicate function can be used to write arbitrary filters. The
18015
- * function is called for each element of `array`. The final result is an array of those
18016
- * elements that the predicate returned true for.
18154
+ * - `function(value, index, array)`: A predicate function can be used to write arbitrary filters.
18155
+ * The function is called for each element of the array, with the element, its index, and
18156
+ * the entire array itself as arguments.
18157
+ *
18158
+ * The final result is an array of those elements that the predicate returned true for.
18017
18159
  *
18018
18160
  * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in
18019
18161
  * determining if the expected value (from the filter expression) and actual value (from
@@ -18138,10 +18280,6 @@ function filterFilter() {
18138
18280
  };
18139
18281
  }
18140
18282
 
18141
- function hasCustomToString(obj) {
18142
- return isFunction(obj.toString) && obj.toString !== Object.prototype.toString;
18143
- }
18144
-
18145
18283
  // Helper functions for `filterFilter`
18146
18284
  function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
18147
18285
  var shouldMatchPrimitives = isObject(expression) && ('$' in expression);
@@ -18314,9 +18452,10 @@ function currencyFilter($locale) {
18314
18452
  * @description
18315
18453
  * Formats a number as text.
18316
18454
  *
18455
+ * If the input is null or undefined, it will just be returned.
18456
+ * If the input is infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned.
18317
18457
  * If the input is not a number an empty string is returned.
18318
18458
  *
18319
- * If the input is an infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned.
18320
18459
  *
18321
18460
  * @param {number|string} number Number to format.
18322
18461
  * @param {(number|string)=} fractionSize Number of decimal places to round the number to.
@@ -18945,7 +19084,7 @@ function limitToFilter() {
18945
19084
  * @description
18946
19085
  * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
18947
19086
  * for strings and numerically for numbers. Note: if you notice numbers are not being sorted
18948
- * correctly, make sure they are actually being saved as numbers and not strings.
19087
+ * as expected, make sure they are actually being saved as numbers and not strings.
18949
19088
  *
18950
19089
  * @param {Array} array The array to sort.
18951
19090
  * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be
@@ -19020,19 +19159,40 @@ function limitToFilter() {
19020
19159
  {name:'Mike', phone:'555-4321', age:21},
19021
19160
  {name:'Adam', phone:'555-5678', age:35},
19022
19161
  {name:'Julie', phone:'555-8765', age:29}];
19023
- $scope.predicate = '-age';
19162
+ $scope.predicate = 'age';
19163
+ $scope.reverse = true;
19164
+ $scope.order = function(predicate) {
19165
+ $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
19166
+ $scope.predicate = predicate;
19167
+ };
19024
19168
  }]);
19025
19169
  </script>
19170
+ <style type="text/css">
19171
+ .sortorder:after {
19172
+ content: '\25b2';
19173
+ }
19174
+ .sortorder.reverse:after {
19175
+ content: '\25bc';
19176
+ }
19177
+ </style>
19026
19178
  <div ng-controller="ExampleController">
19027
19179
  <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
19028
19180
  <hr/>
19029
19181
  [ <a href="" ng-click="predicate=''">unsorted</a> ]
19030
19182
  <table class="friend">
19031
19183
  <tr>
19032
- <th><a href="" ng-click="predicate = 'name'; reverse=false">Name</a>
19033
- (<a href="" ng-click="predicate = '-name'; reverse=false">^</a>)</th>
19034
- <th><a href="" ng-click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th>
19035
- <th><a href="" ng-click="predicate = 'age'; reverse=!reverse">Age</a></th>
19184
+ <th>
19185
+ <a href="" ng-click="order('name')">Name</a>
19186
+ <span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
19187
+ </th>
19188
+ <th>
19189
+ <a href="" ng-click="order('phone')">Phone Number</a>
19190
+ <span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
19191
+ </th>
19192
+ <th>
19193
+ <a href="" ng-click="order('age')">Age</a>
19194
+ <span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
19195
+ </th>
19036
19196
  </tr>
19037
19197
  <tr ng-repeat="friend in friends | orderBy:predicate:reverse">
19038
19198
  <td>{{friend.name}}</td>
@@ -19092,90 +19252,116 @@ function limitToFilter() {
19092
19252
  orderByFilter.$inject = ['$parse'];
19093
19253
  function orderByFilter($parse) {
19094
19254
  return function(array, sortPredicate, reverseOrder) {
19255
+
19095
19256
  if (!(isArrayLike(array))) return array;
19096
- sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate];
19257
+
19258
+ if (!isArray(sortPredicate)) { sortPredicate = [sortPredicate]; }
19097
19259
  if (sortPredicate.length === 0) { sortPredicate = ['+']; }
19098
- sortPredicate = sortPredicate.map(function(predicate) {
19099
- var descending = false, get = predicate || identity;
19100
- if (isString(predicate)) {
19260
+
19261
+ var predicates = processPredicates(sortPredicate, reverseOrder);
19262
+
19263
+ // The next three lines are a version of a Swartzian Transform idiom from Perl
19264
+ // (sometimes called the Decorate-Sort-Undecorate idiom)
19265
+ // See https://en.wikipedia.org/wiki/Schwartzian_transform
19266
+ var compareValues = Array.prototype.map.call(array, getComparisonObject);
19267
+ compareValues.sort(doComparison);
19268
+ array = compareValues.map(function(item) { return item.value; });
19269
+
19270
+ return array;
19271
+
19272
+ function getComparisonObject(value, index) {
19273
+ return {
19274
+ value: value,
19275
+ predicateValues: predicates.map(function(predicate) {
19276
+ return getPredicateValue(predicate.get(value), index);
19277
+ })
19278
+ };
19279
+ }
19280
+
19281
+ function doComparison(v1, v2) {
19282
+ var result = 0;
19283
+ for (var index=0, length = predicates.length; index < length; ++index) {
19284
+ result = compare(v1.predicateValues[index], v2.predicateValues[index]) * predicates[index].descending;
19285
+ if (result) break;
19286
+ }
19287
+ return result;
19288
+ }
19289
+ };
19290
+
19291
+ function processPredicates(sortPredicate, reverseOrder) {
19292
+ reverseOrder = reverseOrder ? -1 : 1;
19293
+ return sortPredicate.map(function(predicate) {
19294
+ var descending = 1, get = identity;
19295
+
19296
+ if (isFunction(predicate)) {
19297
+ get = predicate;
19298
+ } else if (isString(predicate)) {
19101
19299
  if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
19102
- descending = predicate.charAt(0) == '-';
19300
+ descending = predicate.charAt(0) == '-' ? -1 : 1;
19103
19301
  predicate = predicate.substring(1);
19104
19302
  }
19105
- if (predicate === '') {
19106
- // Effectively no predicate was passed so we compare identity
19107
- return reverseComparator(compare, descending);
19108
- }
19109
- get = $parse(predicate);
19110
- if (get.constant) {
19111
- var key = get();
19112
- return reverseComparator(function(a, b) {
19113
- return compare(a[key], b[key]);
19114
- }, descending);
19303
+ if (predicate !== '') {
19304
+ get = $parse(predicate);
19305
+ if (get.constant) {
19306
+ var key = get();
19307
+ get = function(value) { return value[key]; };
19308
+ }
19115
19309
  }
19116
19310
  }
19117
- return reverseComparator(function(a, b) {
19118
- return compare(get(a),get(b));
19119
- }, descending);
19311
+ return { get: get, descending: descending * reverseOrder };
19120
19312
  });
19121
- return slice.call(array).sort(reverseComparator(comparator, reverseOrder));
19313
+ }
19122
19314
 
19123
- function comparator(o1, o2) {
19124
- for (var i = 0; i < sortPredicate.length; i++) {
19125
- var comp = sortPredicate[i](o1, o2);
19126
- if (comp !== 0) return comp;
19127
- }
19128
- return 0;
19129
- }
19130
- function reverseComparator(comp, descending) {
19131
- return descending
19132
- ? function(a, b) {return comp(b,a);}
19133
- : comp;
19315
+ function isPrimitive(value) {
19316
+ switch (typeof value) {
19317
+ case 'number': /* falls through */
19318
+ case 'boolean': /* falls through */
19319
+ case 'string':
19320
+ return true;
19321
+ default:
19322
+ return false;
19134
19323
  }
19324
+ }
19135
19325
 
19136
- function isPrimitive(value) {
19137
- switch (typeof value) {
19138
- case 'number': /* falls through */
19139
- case 'boolean': /* falls through */
19140
- case 'string':
19141
- return true;
19142
- default:
19143
- return false;
19144
- }
19326
+ function objectValue(value, index) {
19327
+ // If `valueOf` is a valid function use that
19328
+ if (typeof value.valueOf === 'function') {
19329
+ value = value.valueOf();
19330
+ if (isPrimitive(value)) return value;
19145
19331
  }
19146
-
19147
- function objectToString(value) {
19148
- if (value === null) return 'null';
19149
- if (typeof value.valueOf === 'function') {
19150
- value = value.valueOf();
19151
- if (isPrimitive(value)) return value;
19152
- }
19153
- if (typeof value.toString === 'function') {
19154
- value = value.toString();
19155
- if (isPrimitive(value)) return value;
19156
- }
19157
- return '';
19332
+ // If `toString` is a valid function and not the one from `Object.prototype` use that
19333
+ if (hasCustomToString(value)) {
19334
+ value = value.toString();
19335
+ if (isPrimitive(value)) return value;
19158
19336
  }
19337
+ // We have a basic object so we use the position of the object in the collection
19338
+ return index;
19339
+ }
19159
19340
 
19160
- function compare(v1, v2) {
19161
- var t1 = typeof v1;
19162
- var t2 = typeof v2;
19163
- if (t1 === t2 && t1 === "object") {
19164
- v1 = objectToString(v1);
19165
- v2 = objectToString(v2);
19166
- }
19167
- if (t1 === t2) {
19168
- if (t1 === "string") {
19169
- v1 = v1.toLowerCase();
19170
- v2 = v2.toLowerCase();
19171
- }
19172
- if (v1 === v2) return 0;
19173
- return v1 < v2 ? -1 : 1;
19174
- } else {
19175
- return t1 < t2 ? -1 : 1;
19341
+ function getPredicateValue(value, index) {
19342
+ var type = typeof value;
19343
+ if (value === null) {
19344
+ type = 'string';
19345
+ value = 'null';
19346
+ } else if (type === 'string') {
19347
+ value = value.toLowerCase();
19348
+ } else if (type === 'object') {
19349
+ value = objectValue(value, index);
19350
+ }
19351
+ return { value: value, type: type };
19352
+ }
19353
+
19354
+ function compare(v1, v2) {
19355
+ var result = 0;
19356
+ if (v1.type === v2.type) {
19357
+ if (v1.value !== v2.value) {
19358
+ result = v1.value < v2.value ? -1 : 1;
19176
19359
  }
19360
+ } else {
19361
+ result = v1.type < v2.type ? -1 : 1;
19177
19362
  }
19178
- };
19363
+ return result;
19364
+ }
19179
19365
  }
19180
19366
 
19181
19367
  function ngDirective(directive) {
@@ -19429,6 +19615,13 @@ var htmlAnchorDirective = valueFn({
19429
19615
  * @priority 100
19430
19616
  *
19431
19617
  * @description
19618
+ * Sets the `checked` attribute on the element, if the expression inside `ngChecked` is truthy.
19619
+ *
19620
+ * Note that this directive should not be used together with {@link ngModel `ngModel`},
19621
+ * as this can lead to unexpected behavior.
19622
+ *
19623
+ * ### Why do we need `ngChecked`?
19624
+ *
19432
19625
  * The HTML specification does not require browsers to preserve the values of boolean attributes
19433
19626
  * such as checked. (Their presence means true and their absence means false.)
19434
19627
  * If we put an Angular interpolation expression into such an attribute then the
@@ -19453,7 +19646,7 @@ var htmlAnchorDirective = valueFn({
19453
19646
  *
19454
19647
  * @element INPUT
19455
19648
  * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,
19456
- * then special attribute "checked" will be set on the element
19649
+ * then the `checked` attribute will be set on the element
19457
19650
  */
19458
19651
 
19459
19652
 
@@ -20195,7 +20388,7 @@ var ngFormDirective = formDirectiveFactory(true);
20195
20388
  var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/;
20196
20389
  var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
20197
20390
  var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
20198
- var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
20391
+ var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/;
20199
20392
  var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
20200
20393
  var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/;
20201
20394
  var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/;
@@ -20794,6 +20987,16 @@ var inputType = {
20794
20987
  * error docs for more information and an example of how to convert your model if necessary.
20795
20988
  * </div>
20796
20989
  *
20990
+ * ## Issues with HTML5 constraint validation
20991
+ *
20992
+ * In browsers that follow the
20993
+ * [HTML5 specification](https://html.spec.whatwg.org/multipage/forms.html#number-state-%28type=number%29),
20994
+ * `input[number]` does not work as expected with {@link ngModelOptions `ngModelOptions.allowInvalid`}.
20995
+ * If a non-number is entered in the input, the browser will report the value as an empty string,
20996
+ * which means the view / model values in `ngModel` and subsequently the scope value
20997
+ * will also be an empty string.
20998
+ *
20999
+ *
20797
21000
  * @param {string} ngModel Assignable angular expression to data-bind to.
20798
21001
  * @param {string=} name Property name of the form under which the control is published.
20799
21002
  * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
@@ -21085,12 +21288,15 @@ var inputType = {
21085
21288
  * HTML radio button.
21086
21289
  *
21087
21290
  * @param {string} ngModel Assignable angular expression to data-bind to.
21088
- * @param {string} value The value to which the expression should be set when selected.
21291
+ * @param {string} value The value to which the `ngModel` expression should be set when selected.
21292
+ * Note that `value` only supports `string` values, i.e. the scope model needs to be a string,
21293
+ * too. Use `ngValue` if you need complex models (`number`, `object`, ...).
21089
21294
  * @param {string=} name Property name of the form under which the control is published.
21090
21295
  * @param {string=} ngChange Angular expression to be executed when input changes due to user
21091
21296
  * interaction with the input element.
21092
- * @param {string} ngValue Angular expression which sets the value to which the expression should
21093
- * be set when selected.
21297
+ * @param {string} ngValue Angular expression to which `ngModel` will be be set when the radio
21298
+ * is selected. Should be used instead of the `value` attribute if you need
21299
+ * a non-string `ngModel` (`boolean`, `array`, ...).
21094
21300
  *
21095
21301
  * @example
21096
21302
  <example name="radio-input-directive" module="radioExample">
@@ -22330,7 +22536,7 @@ function classDirective(name, selector) {
22330
22536
  * @example Example that demonstrates basic bindings via ngClass directive.
22331
22537
  <example>
22332
22538
  <file name="index.html">
22333
- <p ng-class="{strike: deleted, bold: important, red: error}">Map Syntax Example</p>
22539
+ <p ng-class="{strike: deleted, bold: important, 'has-error': error}">Map Syntax Example</p>
22334
22540
  <label>
22335
22541
  <input type="checkbox" ng-model="deleted">
22336
22542
  deleted (apply "strike" class)
@@ -22341,7 +22547,7 @@ function classDirective(name, selector) {
22341
22547
  </label><br>
22342
22548
  <label>
22343
22549
  <input type="checkbox" ng-model="error">
22344
- error (apply "red" class)
22550
+ error (apply "has-error" class)
22345
22551
  </label>
22346
22552
  <hr>
22347
22553
  <p ng-class="style">Using String Syntax</p>
@@ -22370,6 +22576,10 @@ function classDirective(name, selector) {
22370
22576
  .red {
22371
22577
  color: red;
22372
22578
  }
22579
+ .has-error {
22580
+ color: red;
22581
+ background-color: yellow;
22582
+ }
22373
22583
  .orange {
22374
22584
  color: orange;
22375
22585
  }
@@ -22380,13 +22590,13 @@ function classDirective(name, selector) {
22380
22590
  it('should let you toggle the class', function() {
22381
22591
 
22382
22592
  expect(ps.first().getAttribute('class')).not.toMatch(/bold/);
22383
- expect(ps.first().getAttribute('class')).not.toMatch(/red/);
22593
+ expect(ps.first().getAttribute('class')).not.toMatch(/has-error/);
22384
22594
 
22385
22595
  element(by.model('important')).click();
22386
22596
  expect(ps.first().getAttribute('class')).toMatch(/bold/);
22387
22597
 
22388
22598
  element(by.model('error')).click();
22389
- expect(ps.first().getAttribute('class')).toMatch(/red/);
22599
+ expect(ps.first().getAttribute('class')).toMatch(/has-error/);
22390
22600
  });
22391
22601
 
22392
22602
  it('should let you toggle string example', function() {
@@ -23514,6 +23724,7 @@ forEach(
23514
23724
  * @ngdoc directive
23515
23725
  * @name ngIf
23516
23726
  * @restrict A
23727
+ * @multiElement
23517
23728
  *
23518
23729
  * @description
23519
23730
  * The `ngIf` directive removes or recreates a portion of the DOM tree based on an
@@ -23812,8 +24023,8 @@ var ngIfDirective = ['$animate', function($animate) {
23812
24023
  * @param {Object} angularEvent Synthetic event object.
23813
24024
  * @param {String} src URL of content to load.
23814
24025
  */
23815
- var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce',
23816
- function($templateRequest, $anchorScroll, $animate, $sce) {
24026
+ var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
24027
+ function($templateRequest, $anchorScroll, $animate) {
23817
24028
  return {
23818
24029
  restrict: 'ECA',
23819
24030
  priority: 400,
@@ -23849,7 +24060,7 @@ var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce
23849
24060
  }
23850
24061
  };
23851
24062
 
23852
- scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) {
24063
+ scope.$watch(srcExp, function ngIncludeWatchAction(src) {
23853
24064
  var afterAnimation = function() {
23854
24065
  if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
23855
24066
  $anchorScroll();
@@ -25220,7 +25431,7 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
25220
25431
  * - `debounce`: integer value which contains the debounce model update value in milliseconds. A
25221
25432
  * value of 0 triggers an immediate update. If an object is supplied instead, you can specify a
25222
25433
  * custom value for each event. For example:
25223
- * `ng-model-options="{ updateOn: 'default blur', debounce: {'default': 500, 'blur': 0} }"`
25434
+ * `ng-model-options="{ updateOn: 'default blur', debounce: { 'default': 500, 'blur': 0 } }"`
25224
25435
  * - `allowInvalid`: boolean value which indicates that the model can be set with values that did
25225
25436
  * not validate correctly instead of the default behavior of setting the model to undefined.
25226
25437
  * - `getterSetter`: boolean value which determines whether or not to treat functions bound to
@@ -25470,7 +25681,9 @@ function addSetValidityMethod(context) {
25470
25681
  function isObjectEmpty(obj) {
25471
25682
  if (obj) {
25472
25683
  for (var prop in obj) {
25473
- return false;
25684
+ if (obj.hasOwnProperty(prop)) {
25685
+ return false;
25686
+ }
25474
25687
  }
25475
25688
  }
25476
25689
  return true;
@@ -25802,19 +26015,41 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
25802
26015
  this.disabled = disabled;
25803
26016
  }
25804
26017
 
26018
+ function getOptionValuesKeys(optionValues) {
26019
+ var optionValuesKeys;
26020
+
26021
+ if (!keyName && isArrayLike(optionValues)) {
26022
+ optionValuesKeys = optionValues;
26023
+ } else {
26024
+ // if object, extract keys, in enumeration order, unsorted
26025
+ optionValuesKeys = [];
26026
+ for (var itemKey in optionValues) {
26027
+ if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {
26028
+ optionValuesKeys.push(itemKey);
26029
+ }
26030
+ }
26031
+ }
26032
+ return optionValuesKeys;
26033
+ }
26034
+
25805
26035
  return {
25806
26036
  trackBy: trackBy,
25807
26037
  getTrackByValue: getTrackByValue,
25808
- getWatchables: $parse(valuesFn, function(values) {
26038
+ getWatchables: $parse(valuesFn, function(optionValues) {
25809
26039
  // Create a collection of things that we would like to watch (watchedArray)
25810
26040
  // so that they can all be watched using a single $watchCollection
25811
26041
  // that only runs the handler once if anything changes
25812
26042
  var watchedArray = [];
25813
- values = values || [];
26043
+ optionValues = optionValues || [];
26044
+
26045
+ var optionValuesKeys = getOptionValuesKeys(optionValues);
26046
+ var optionValuesLength = optionValuesKeys.length;
26047
+ for (var index = 0; index < optionValuesLength; index++) {
26048
+ var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index];
26049
+ var value = optionValues[key];
25814
26050
 
25815
- Object.keys(values).forEach(function getWatchable(key) {
25816
- var locals = getLocals(values[key], key);
25817
- var selectValue = getTrackByValueFn(values[key], locals);
26051
+ var locals = getLocals(optionValues[key], key);
26052
+ var selectValue = getTrackByValueFn(optionValues[key], locals);
25818
26053
  watchedArray.push(selectValue);
25819
26054
 
25820
26055
  // Only need to watch the displayFn if there is a specific label expression
@@ -25828,7 +26063,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
25828
26063
  var disableWhen = disableWhenFn(scope, locals);
25829
26064
  watchedArray.push(disableWhen);
25830
26065
  }
25831
- });
26066
+ }
25832
26067
  return watchedArray;
25833
26068
  }),
25834
26069
 
@@ -25840,21 +26075,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
25840
26075
  // The option values were already computed in the `getWatchables` fn,
25841
26076
  // which must have been called to trigger `getOptions`
25842
26077
  var optionValues = valuesFn(scope) || [];
25843
- var optionValuesKeys;
25844
-
25845
-
25846
- if (!keyName && isArrayLike(optionValues)) {
25847
- optionValuesKeys = optionValues;
25848
- } else {
25849
- // if object, extract keys, in enumeration order, unsorted
25850
- optionValuesKeys = [];
25851
- for (var itemKey in optionValues) {
25852
- if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {
25853
- optionValuesKeys.push(itemKey);
25854
- }
25855
- }
25856
- }
25857
-
26078
+ var optionValuesKeys = getOptionValuesKeys(optionValues);
25858
26079
  var optionValuesLength = optionValuesKeys.length;
25859
26080
 
25860
26081
  for (var index = 0; index < optionValuesLength; index++) {
@@ -26216,8 +26437,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
26216
26437
  // Check to see if the value has changed due to the update to the options
26217
26438
  if (!ngModelCtrl.$isEmpty(previousValue)) {
26218
26439
  var nextValue = selectCtrl.readValue();
26219
- if (ngOptions.trackBy && !equals(previousValue, nextValue) ||
26220
- previousValue !== nextValue) {
26440
+ if (ngOptions.trackBy ? !equals(previousValue, nextValue) : previousValue !== nextValue) {
26221
26441
  ngModelCtrl.$setViewValue(nextValue);
26222
26442
  ngModelCtrl.$render();
26223
26443
  }
@@ -26471,6 +26691,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
26471
26691
  /**
26472
26692
  * @ngdoc directive
26473
26693
  * @name ngRepeat
26694
+ * @multiElement
26474
26695
  *
26475
26696
  * @description
26476
26697
  * The `ngRepeat` directive instantiates a template once per item from a collection. Each template
@@ -26565,6 +26786,15 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
26565
26786
  * </div>
26566
26787
  * ```
26567
26788
  *
26789
+ * <div class="alert alert-warning">
26790
+ * **Note:** `track by` must always be the last expression:
26791
+ * </div>
26792
+ * ```
26793
+ * <div ng-repeat="model in collection | orderBy: 'id' as filtered_result track by model.id">
26794
+ * {{model.name}}
26795
+ * </div>
26796
+ * ```
26797
+ *
26568
26798
  * # Special repeat start and end points
26569
26799
  * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
26570
26800
  * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.
@@ -26636,8 +26866,9 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
26636
26866
  * which can be used to associate the objects in the collection with the DOM elements. If no tracking expression
26637
26867
  * is specified, ng-repeat associates elements by identity. It is an error to have
26638
26868
  * more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are
26639
- * mapped to the same DOM element, which is not possible.) If filters are used in the expression, they should be
26640
- * applied before the tracking expression.
26869
+ * mapped to the same DOM element, which is not possible.)
26870
+ *
26871
+ * Note that the tracking expression must come last, after any filters, and the alias expression.
26641
26872
  *
26642
26873
  * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
26643
26874
  * will be associated by item identity in the array.
@@ -26990,6 +27221,7 @@ var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
26990
27221
  /**
26991
27222
  * @ngdoc directive
26992
27223
  * @name ngShow
27224
+ * @multiElement
26993
27225
  *
26994
27226
  * @description
26995
27227
  * The `ngShow` directive shows or hides the given HTML element based on the expression
@@ -27165,6 +27397,7 @@ var ngShowDirective = ['$animate', function($animate) {
27165
27397
  /**
27166
27398
  * @ngdoc directive
27167
27399
  * @name ngHide
27400
+ * @multiElement
27168
27401
  *
27169
27402
  * @description
27170
27403
  * The `ngHide` directive shows or hides the given HTML element based on the expression