rails-angularjs 1.4.0.pre.rc.1 → 1.4.0.pre.rc.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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rails-angularjs/version.rb +1 -1
  3. data/vendor/assets/javascripts/angular-animate.js +247 -159
  4. data/vendor/assets/javascripts/angular-animate.min.js +45 -44
  5. data/vendor/assets/javascripts/angular-animate.min.js.map +3 -3
  6. data/vendor/assets/javascripts/angular-aria.js +1 -1
  7. data/vendor/assets/javascripts/angular-aria.min.js +1 -1
  8. data/vendor/assets/javascripts/angular-cookies.js +1 -1
  9. data/vendor/assets/javascripts/angular-cookies.min.js +1 -1
  10. data/vendor/assets/javascripts/angular-loader.js +2 -2
  11. data/vendor/assets/javascripts/angular-loader.min.js +2 -2
  12. data/vendor/assets/javascripts/angular-message-format.js +1 -1
  13. data/vendor/assets/javascripts/angular-message-format.min.js +1 -1
  14. data/vendor/assets/javascripts/angular-messages.js +1 -1
  15. data/vendor/assets/javascripts/angular-messages.min.js +1 -1
  16. data/vendor/assets/javascripts/angular-mocks.js +1 -1
  17. data/vendor/assets/javascripts/angular-resource.js +3 -3
  18. data/vendor/assets/javascripts/angular-resource.min.js +8 -8
  19. data/vendor/assets/javascripts/angular-resource.min.js.map +1 -1
  20. data/vendor/assets/javascripts/angular-route.js +1 -1
  21. data/vendor/assets/javascripts/angular-route.min.js +1 -1
  22. data/vendor/assets/javascripts/angular-sanitize.js +1 -1
  23. data/vendor/assets/javascripts/angular-sanitize.min.js +1 -1
  24. data/vendor/assets/javascripts/angular-scenario.js +316 -143
  25. data/vendor/assets/javascripts/angular-touch.js +12 -10
  26. data/vendor/assets/javascripts/angular-touch.min.js +8 -8
  27. data/vendor/assets/javascripts/angular-touch.min.js.map +2 -2
  28. data/vendor/assets/javascripts/angular.js +316 -143
  29. data/vendor/assets/javascripts/angular.min.js +267 -265
  30. data/vendor/assets/javascripts/angular.min.js.map +3 -3
  31. metadata +2 -3
@@ -9190,7 +9190,7 @@ return jQuery;
9190
9190
  }));
9191
9191
 
9192
9192
  /**
9193
- * @license AngularJS v1.4.0-rc.1
9193
+ * @license AngularJS v1.4.0-rc.2
9194
9194
  * (c) 2010-2015 Google, Inc. http://angularjs.org
9195
9195
  * License: MIT
9196
9196
  */
@@ -9249,7 +9249,7 @@ function minErr(module, ErrorConstructor) {
9249
9249
  return match;
9250
9250
  });
9251
9251
 
9252
- message += '\nhttp://errors.angularjs.org/1.4.0-rc.1/' +
9252
+ message += '\nhttp://errors.angularjs.org/1.4.0-rc.2/' +
9253
9253
  (module ? module + '/' : '') + code;
9254
9254
 
9255
9255
  for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
@@ -9297,6 +9297,7 @@ function minErr(module, ErrorConstructor) {
9297
9297
  isUndefined: true,
9298
9298
  isDefined: true,
9299
9299
  isObject: true,
9300
+ isBlankObject: true,
9300
9301
  isString: true,
9301
9302
  isNumber: true,
9302
9303
  isDate: true,
@@ -9436,6 +9437,7 @@ var
9436
9437
  splice = [].splice,
9437
9438
  push = [].push,
9438
9439
  toString = Object.prototype.toString,
9440
+ getPrototypeOf = Object.getPrototypeOf,
9439
9441
  ngMinErr = minErr('ng'),
9440
9442
 
9441
9443
  /** @name angular */
@@ -9461,7 +9463,9 @@ function isArrayLike(obj) {
9461
9463
  return false;
9462
9464
  }
9463
9465
 
9464
- var length = obj.length;
9466
+ // Support: iOS 8.2 (not reproducible in simulator)
9467
+ // "length" in obj used to prevent JIT error (gh-11508)
9468
+ var length = "length" in Object(obj) && obj.length;
9465
9469
 
9466
9470
  if (obj.nodeType === NODE_TYPE_ELEMENT && length) {
9467
9471
  return true;
@@ -9526,12 +9530,25 @@ function forEach(obj, iterator, context) {
9526
9530
  }
9527
9531
  } else if (obj.forEach && obj.forEach !== forEach) {
9528
9532
  obj.forEach(iterator, context, obj);
9529
- } else {
9533
+ } else if (isBlankObject(obj)) {
9534
+ // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
9535
+ for (key in obj) {
9536
+ iterator.call(context, obj[key], key, obj);
9537
+ }
9538
+ } else if (typeof obj.hasOwnProperty === 'function') {
9539
+ // Slow path for objects inheriting Object.prototype, hasOwnProperty check needed
9530
9540
  for (key in obj) {
9531
9541
  if (obj.hasOwnProperty(key)) {
9532
9542
  iterator.call(context, obj[key], key, obj);
9533
9543
  }
9534
9544
  }
9545
+ } else {
9546
+ // Slow path for objects which do not have a method `hasOwnProperty`
9547
+ for (key in obj) {
9548
+ if (hasOwnProperty.call(obj, key)) {
9549
+ iterator.call(context, obj[key], key, obj);
9550
+ }
9551
+ }
9535
9552
  }
9536
9553
  }
9537
9554
  return obj;
@@ -9757,6 +9774,16 @@ function isObject(value) {
9757
9774
  }
9758
9775
 
9759
9776
 
9777
+ /**
9778
+ * Determine if a value is an object with a null prototype
9779
+ *
9780
+ * @returns {boolean} True if `value` is an `Object` with a null prototype
9781
+ */
9782
+ function isBlankObject(value) {
9783
+ return value !== null && typeof value === 'object' && !getPrototypeOf(value);
9784
+ }
9785
+
9786
+
9760
9787
  /**
9761
9788
  * @ngdoc function
9762
9789
  * @name angular.isString
@@ -10040,7 +10067,7 @@ function copy(source, destination, stackSource, stackDest) {
10040
10067
  destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
10041
10068
  destination.lastIndex = source.lastIndex;
10042
10069
  } else if (isObject(source)) {
10043
- var emptyObject = Object.create(Object.getPrototypeOf(source));
10070
+ var emptyObject = Object.create(getPrototypeOf(source));
10044
10071
  destination = copy(source, emptyObject, stackSource, stackDest);
10045
10072
  }
10046
10073
  }
@@ -10059,7 +10086,7 @@ function copy(source, destination, stackSource, stackDest) {
10059
10086
  stackDest.push(destination);
10060
10087
  }
10061
10088
 
10062
- var result;
10089
+ var result, key;
10063
10090
  if (isArray(source)) {
10064
10091
  destination.length = 0;
10065
10092
  for (var i = 0; i < source.length; i++) {
@@ -10079,21 +10106,40 @@ function copy(source, destination, stackSource, stackDest) {
10079
10106
  delete destination[key];
10080
10107
  });
10081
10108
  }
10082
- for (var key in source) {
10083
- if (source.hasOwnProperty(key)) {
10084
- result = copy(source[key], null, stackSource, stackDest);
10085
- if (isObject(source[key])) {
10086
- stackSource.push(source[key]);
10087
- stackDest.push(result);
10109
+ if (isBlankObject(source)) {
10110
+ // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
10111
+ for (key in source) {
10112
+ putValue(key, source[key], destination, stackSource, stackDest);
10113
+ }
10114
+ } else if (source && typeof source.hasOwnProperty === 'function') {
10115
+ // Slow path, which must rely on hasOwnProperty
10116
+ for (key in source) {
10117
+ if (source.hasOwnProperty(key)) {
10118
+ putValue(key, source[key], destination, stackSource, stackDest);
10119
+ }
10120
+ }
10121
+ } else {
10122
+ // Slowest path --- hasOwnProperty can't be called as a method
10123
+ for (key in source) {
10124
+ if (hasOwnProperty.call(source, key)) {
10125
+ putValue(key, source[key], destination, stackSource, stackDest);
10088
10126
  }
10089
- destination[key] = result;
10090
10127
  }
10091
10128
  }
10092
10129
  setHashKey(destination,h);
10093
10130
  }
10094
-
10095
10131
  }
10096
10132
  return destination;
10133
+
10134
+ function putValue(key, val, destination, stackSource, stackDest) {
10135
+ // No context allocation, trivial outer scope, easily inlined
10136
+ var result = copy(val, null, stackSource, stackDest);
10137
+ if (isObject(val)) {
10138
+ stackSource.push(val);
10139
+ stackDest.push(result);
10140
+ }
10141
+ destination[key] = result;
10142
+ }
10097
10143
  }
10098
10144
 
10099
10145
  /**
@@ -10174,14 +10220,14 @@ function equals(o1, o2) {
10174
10220
  } else {
10175
10221
  if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
10176
10222
  isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
10177
- keySet = {};
10223
+ keySet = createMap();
10178
10224
  for (key in o1) {
10179
10225
  if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
10180
10226
  if (!equals(o1[key], o2[key])) return false;
10181
10227
  keySet[key] = true;
10182
10228
  }
10183
10229
  for (key in o2) {
10184
- if (!keySet.hasOwnProperty(key) &&
10230
+ if (!(key in keySet) &&
10185
10231
  key.charAt(0) !== '$' &&
10186
10232
  o2[key] !== undefined &&
10187
10233
  !isFunction(o2[key])) return false;
@@ -10218,17 +10264,17 @@ var csp = function() {
10218
10264
  * @name ngJq
10219
10265
  *
10220
10266
  * @element ANY
10221
- * @param {string=} the name of the library available under `window`
10267
+ * @param {string=} ngJq the name of the library available under `window`
10222
10268
  * to be used for angular.element
10223
10269
  * @description
10224
10270
  * Use this directive to force the angular.element library. This should be
10225
10271
  * used to force either jqLite by leaving ng-jq blank or setting the name of
10226
10272
  * the jquery variable under window (eg. jQuery).
10227
10273
  *
10228
- * Since this directive is global for the angular library, it is recommended
10229
- * that it's added to the same element as ng-app or the HTML element, but it is not mandatory.
10230
- * It needs to be noted that only the first instance of `ng-jq` will be used and all others
10231
- * ignored.
10274
+ * Since angular looks for this directive when it is loaded (doesn't wait for the
10275
+ * DOMContentLoaded event), it must be placed on an element that comes before the script
10276
+ * which loads angular. Also, only the first instance of `ng-jq` will be used and all
10277
+ * others ignored.
10232
10278
  *
10233
10279
  * @example
10234
10280
  * This example shows how to force jqLite using the `ngJq` directive to the `html` tag.
@@ -11478,11 +11524,11 @@ function toDebugString(obj) {
11478
11524
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
11479
11525
  */
11480
11526
  var version = {
11481
- full: '1.4.0-rc.1', // all of these placeholder strings will be replaced by grunt's
11527
+ full: '1.4.0-rc.2', // all of these placeholder strings will be replaced by grunt's
11482
11528
  major: 1, // package task
11483
11529
  minor: 4,
11484
11530
  dot: 0,
11485
- codeName: 'sartorial-chronography'
11531
+ codeName: 'rocket-zambonimation'
11486
11532
  };
11487
11533
 
11488
11534
 
@@ -11665,7 +11711,7 @@ function publishExternalAPI(angular) {
11665
11711
  * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most
11666
11712
  * commonly needed functionality with the goal of having a very small footprint.</div>
11667
11713
  *
11668
- * To use jQuery, simply load it before `DOMContentLoaded` event fired.
11714
+ * To use `jQuery`, simply ensure it is loaded before the `angular.js` file.
11669
11715
  *
11670
11716
  * <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or
11671
11717
  * jqLite; they are never raw DOM references.</div>
@@ -11681,7 +11727,7 @@ function publishExternalAPI(angular) {
11681
11727
  * - [`children()`](http://api.jquery.com/children/) - Does not support selectors
11682
11728
  * - [`clone()`](http://api.jquery.com/clone/)
11683
11729
  * - [`contents()`](http://api.jquery.com/contents/)
11684
- * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`
11730
+ * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. As a setter, does not convert numbers to strings or append 'px'.
11685
11731
  * - [`data()`](http://api.jquery.com/data/)
11686
11732
  * - [`detach()`](http://api.jquery.com/detach/)
11687
11733
  * - [`empty()`](http://api.jquery.com/empty/)
@@ -12925,7 +12971,7 @@ function annotate(fn, strictDi, name) {
12925
12971
  * Return an instance of the service.
12926
12972
  *
12927
12973
  * @param {string} name The name of the instance to retrieve.
12928
- * @param {string} caller An optional string to provide the origin of the function call for error messages.
12974
+ * @param {string=} caller An optional string to provide the origin of the function call for error messages.
12929
12975
  * @return {*} The instance.
12930
12976
  */
12931
12977
 
@@ -12936,8 +12982,8 @@ function annotate(fn, strictDi, name) {
12936
12982
  * @description
12937
12983
  * Invoke the method and supply the method arguments from the `$injector`.
12938
12984
  *
12939
- * @param {!Function} fn The function to invoke. Function parameters are injected according to the
12940
- * {@link guide/di $inject Annotation} rules.
12985
+ * @param {Function|Array.<string|Function>} fn The injectable function to invoke. Function parameters are
12986
+ * injected according to the {@link guide/di $inject Annotation} rules.
12941
12987
  * @param {Object=} self The `this` for the invoked method.
12942
12988
  * @param {Object=} locals Optional object. If preset then any argument names are read from this
12943
12989
  * object first, before the `$injector` is consulted.
@@ -13204,8 +13250,8 @@ function annotate(fn, strictDi, name) {
13204
13250
  * configure your service in a provider.
13205
13251
  *
13206
13252
  * @param {string} name The name of the instance.
13207
- * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand
13208
- * for `$provide.provider(name, {$get: $getFn})`.
13253
+ * @param {Function|Array.<string|Function>} $getFn The injectable $getFn for the instance creation.
13254
+ * Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`.
13209
13255
  * @returns {Object} registered provider instance
13210
13256
  *
13211
13257
  * @example
@@ -13240,7 +13286,8 @@ function annotate(fn, strictDi, name) {
13240
13286
  * as a type/class.
13241
13287
  *
13242
13288
  * @param {string} name The name of the instance.
13243
- * @param {Function} constructor A class (constructor function) that will be instantiated.
13289
+ * @param {Function|Array.<string|Function>} constructor An injectable class (constructor function)
13290
+ * that will be instantiated.
13244
13291
  * @returns {Object} registered provider instance
13245
13292
  *
13246
13293
  * @example
@@ -13339,7 +13386,7 @@ function annotate(fn, strictDi, name) {
13339
13386
  * object which replaces or wraps and delegates to the original service.
13340
13387
  *
13341
13388
  * @param {string} name The name of the service to decorate.
13342
- * @param {function()} decorator This function will be invoked when the service needs to be
13389
+ * @param {Function|Array.<string|Function>} decorator This function will be invoked when the service needs to be
13343
13390
  * instantiated and should return the decorated service instance. The function is called using
13344
13391
  * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.
13345
13392
  * Local injection arguments:
@@ -13868,6 +13915,7 @@ function $AnchorScrollProvider() {
13868
13915
 
13869
13916
  var $animateMinErr = minErr('$animate');
13870
13917
  var ELEMENT_NODE = 1;
13918
+ var NG_ANIMATE_CLASSNAME = 'ng-animate';
13871
13919
 
13872
13920
  function mergeClasses(a,b) {
13873
13921
  if (!a && !b) return '';
@@ -13892,7 +13940,9 @@ function splitClasses(classes) {
13892
13940
  classes = classes.split(' ');
13893
13941
  }
13894
13942
 
13895
- var obj = {};
13943
+ // Use createMap() to prevent class assumptions involving property names in
13944
+ // Object.prototype
13945
+ var obj = createMap();
13896
13946
  forEach(classes, function(klass) {
13897
13947
  // sometimes the split leaves empty string values
13898
13948
  // incase extra spaces were applied to the options
@@ -14097,6 +14147,13 @@ var $AnimateProvider = ['$provide', function($provide) {
14097
14147
  this.classNameFilter = function(expression) {
14098
14148
  if (arguments.length === 1) {
14099
14149
  this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
14150
+ if (this.$$classNameFilter) {
14151
+ var reservedRegex = new RegExp("(\\s+|\\/)" + NG_ANIMATE_CLASSNAME + "(\\s+|\\/)");
14152
+ if (reservedRegex.test(this.$$classNameFilter.toString())) {
14153
+ throw $animateMinErr('nongcls','$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.', NG_ANIMATE_CLASSNAME);
14154
+
14155
+ }
14156
+ }
14100
14157
  }
14101
14158
  return this.$$classNameFilter;
14102
14159
  };
@@ -15995,6 +16052,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15995
16052
  if (!letter || letter !== lowercase(letter)) {
15996
16053
  throw $compileMinErr('baddir', "Directive name '{0}' is invalid. The first character must be a lowercase letter", name);
15997
16054
  }
16055
+ if (name !== name.trim()) {
16056
+ throw $compileMinErr('baddir',
16057
+ "Directive name '{0}' is invalid. The name should not contain leading or trailing whitespaces",
16058
+ name);
16059
+ }
15998
16060
  }
15999
16061
 
16000
16062
  /**
@@ -18179,34 +18241,14 @@ var JSON_ENDS = {
18179
18241
  };
18180
18242
  var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/;
18181
18243
 
18182
- function paramSerializerFactory(jQueryMode) {
18183
-
18184
- function serializeValue(v) {
18185
- if (isObject(v)) {
18186
- return isDate(v) ? v.toISOString() : toJson(v);
18187
- }
18188
- return v;
18244
+ function serializeValue(v) {
18245
+ if (isObject(v)) {
18246
+ return isDate(v) ? v.toISOString() : toJson(v);
18189
18247
  }
18190
-
18191
- return function paramSerializer(params) {
18192
- if (!params) return '';
18193
- var parts = [];
18194
- forEachSorted(params, function(value, key) {
18195
- if (value === null || isUndefined(value)) return;
18196
- if (isArray(value) || isObject(value) && jQueryMode) {
18197
- forEach(value, function(v, k) {
18198
- var keySuffix = jQueryMode ? '[' + (!isArray(value) ? k : '') + ']' : '';
18199
- parts.push(encodeUriQuery(key + keySuffix) + '=' + encodeUriQuery(serializeValue(v)));
18200
- });
18201
- } else {
18202
- parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(value)));
18203
- }
18204
- });
18205
-
18206
- return parts.length > 0 ? parts.join('&') : '';
18207
- };
18248
+ return v;
18208
18249
  }
18209
18250
 
18251
+
18210
18252
  function $HttpParamSerializerProvider() {
18211
18253
  /**
18212
18254
  * @ngdoc service
@@ -18221,7 +18263,22 @@ function $HttpParamSerializerProvider() {
18221
18263
  * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D"` (stringified and encoded representation of an object)
18222
18264
  * */
18223
18265
  this.$get = function() {
18224
- return paramSerializerFactory(false);
18266
+ return function ngParamSerializer(params) {
18267
+ if (!params) return '';
18268
+ var parts = [];
18269
+ forEachSorted(params, function(value, key) {
18270
+ if (value === null || isUndefined(value)) return;
18271
+ if (isArray(value)) {
18272
+ forEach(value, function(v, k) {
18273
+ parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(v)));
18274
+ });
18275
+ } else {
18276
+ parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(value)));
18277
+ }
18278
+ });
18279
+
18280
+ return parts.join('&');
18281
+ };
18225
18282
  };
18226
18283
  }
18227
18284
 
@@ -18234,7 +18291,30 @@ function $HttpParamSerializerJQLikeProvider() {
18234
18291
  * Alternative $http params serializer that follows jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic.
18235
18292
  * */
18236
18293
  this.$get = function() {
18237
- return paramSerializerFactory(true);
18294
+ return function jQueryLikeParamSerializer(params) {
18295
+ if (!params) return '';
18296
+ var parts = [];
18297
+ serialize(params, '', true);
18298
+ return parts.join('&');
18299
+
18300
+ function serialize(toSerialize, prefix, topLevel) {
18301
+ if (toSerialize === null || isUndefined(toSerialize)) return;
18302
+ if (isArray(toSerialize)) {
18303
+ forEach(toSerialize, function(value) {
18304
+ serialize(value, prefix + '[]');
18305
+ });
18306
+ } else if (isObject(toSerialize) && !isDate(toSerialize)) {
18307
+ forEachSorted(toSerialize, function(value, key) {
18308
+ serialize(value, prefix +
18309
+ (topLevel ? '' : '[') +
18310
+ key +
18311
+ (topLevel ? '' : ']'));
18312
+ });
18313
+ } else {
18314
+ parts.push(encodeUriQuery(prefix) + '=' + encodeUriQuery(serializeValue(toSerialize)));
18315
+ }
18316
+ }
18317
+ };
18238
18318
  };
18239
18319
  }
18240
18320
 
@@ -20603,11 +20683,19 @@ var locationPrototype = {
20603
20683
  *
20604
20684
  * Return host of current url.
20605
20685
  *
20686
+ * Note: compared to the non-angular version `location.host` which returns `hostname:port`, this returns the `hostname` portion only.
20687
+ *
20606
20688
  *
20607
20689
  * ```js
20608
20690
  * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
20609
20691
  * var host = $location.host();
20610
20692
  * // => "example.com"
20693
+ *
20694
+ * // given url http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo
20695
+ * host = $location.host();
20696
+ * // => "example.com"
20697
+ * host = location.host;
20698
+ * // => "example.com:8080"
20611
20699
  * ```
20612
20700
  *
20613
20701
  * @return {string} host of current url.
@@ -23364,9 +23452,11 @@ function $ParseProvider() {
23364
23452
  * provide a progress indication, before the promise is resolved or rejected.
23365
23453
  *
23366
23454
  * This method *returns a new promise* which is resolved or rejected via the return value of the
23367
- * `successCallback`, `errorCallback`. It also notifies via the return value of the
23368
- * `notifyCallback` method. The promise cannot be resolved or rejected from the notifyCallback
23369
- * method.
23455
+ * `successCallback`, `errorCallback` (unless that value is a promise, in which case it is resolved
23456
+ * with the value which is resolved in that promise using
23457
+ * [promise chaining](http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promises-queues)).
23458
+ * It also notifies via the return value of the `notifyCallback` method. The promise cannot be
23459
+ * resolved or rejected from the notifyCallback method.
23370
23460
  *
23371
23461
  * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`
23372
23462
  *
@@ -23802,7 +23892,7 @@ function $$RAFProvider() { //rAF
23802
23892
  $window.webkitCancelRequestAnimationFrame;
23803
23893
 
23804
23894
  var rafSupported = !!requestAnimationFrame;
23805
- var raf = rafSupported
23895
+ var rafFn = rafSupported
23806
23896
  ? function(fn) {
23807
23897
  var id = requestAnimationFrame(fn);
23808
23898
  return function() {
@@ -23816,9 +23906,47 @@ function $$RAFProvider() { //rAF
23816
23906
  };
23817
23907
  };
23818
23908
 
23819
- raf.supported = rafSupported;
23909
+ queueFn.supported = rafSupported;
23910
+
23911
+ var cancelLastRAF;
23912
+ var taskCount = 0;
23913
+ var taskQueue = [];
23914
+ return queueFn;
23915
+
23916
+ function flush() {
23917
+ for (var i = 0; i < taskQueue.length; i++) {
23918
+ var task = taskQueue[i];
23919
+ if (task) {
23920
+ taskQueue[i] = null;
23921
+ task();
23922
+ }
23923
+ }
23924
+ taskCount = taskQueue.length = 0;
23925
+ }
23926
+
23927
+ function queueFn(asyncFn) {
23928
+ var index = taskQueue.length;
23929
+
23930
+ taskCount++;
23931
+ taskQueue.push(asyncFn);
23820
23932
 
23821
- return raf;
23933
+ if (index === 0) {
23934
+ cancelLastRAF = rafFn(flush);
23935
+ }
23936
+
23937
+ return function cancelQueueFn() {
23938
+ if (index >= 0) {
23939
+ taskQueue[index] = null;
23940
+ index = null;
23941
+
23942
+ if (--taskCount === 0 && cancelLastRAF) {
23943
+ cancelLastRAF();
23944
+ cancelLastRAF = null;
23945
+ taskQueue.length = 0;
23946
+ }
23947
+ }
23948
+ };
23949
+ }
23822
23950
  }];
23823
23951
  }
23824
23952
 
@@ -29124,11 +29252,11 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
29124
29252
  <form name="myForm" ng-controller="FormController" class="my-form">
29125
29253
  userType: <input name="input" ng-model="userType" required>
29126
29254
  <span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
29127
- <tt>userType = {{userType}}</tt><br>
29128
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>
29129
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>
29130
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br>
29131
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
29255
+ <code>userType = {{userType}}</code><br>
29256
+ <code>myForm.input.$valid = {{myForm.input.$valid}}</code><br>
29257
+ <code>myForm.input.$error = {{myForm.input.$error}}</code><br>
29258
+ <code>myForm.$valid = {{myForm.$valid}}</code><br>
29259
+ <code>myForm.$error.required = {{!!myForm.$error.required}}</code><br>
29132
29260
  </form>
29133
29261
  </file>
29134
29262
  <file name="protractor.js" type="protractor">
@@ -31226,7 +31354,9 @@ function classDirective(name, selector) {
31226
31354
  }
31227
31355
 
31228
31356
  function digestClassCounts(classes, count) {
31229
- var classCounts = element.data('$classCounts') || {};
31357
+ // Use createMap() to prevent class assumptions involving property
31358
+ // names in Object.prototype
31359
+ var classCounts = element.data('$classCounts') || createMap();
31230
31360
  var classesToUpdate = [];
31231
31361
  forEach(classes, function(className) {
31232
31362
  if (count > 0 || classCounts[className]) {
@@ -31609,17 +31739,13 @@ var ngClassEvenDirective = classDirective('Even', 1);
31609
31739
  * document; alternatively, the css rule above must be included in the external stylesheet of the
31610
31740
  * application.
31611
31741
  *
31612
- * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they
31613
- * cannot match the `[ng\:cloak]` selector. To work around this limitation, you must add the css
31614
- * class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below.
31615
- *
31616
31742
  * @element ANY
31617
31743
  *
31618
31744
  * @example
31619
31745
  <example>
31620
31746
  <file name="index.html">
31621
31747
  <div id="template1" ng-cloak>{{ 'hello' }}</div>
31622
- <div id="template2" ng-cloak class="ng-cloak">{{ 'hello IE7' }}</div>
31748
+ <div id="template2" class="ng-cloak">{{ 'world' }}</div>
31623
31749
  </file>
31624
31750
  <file name="protractor.js" type="protractor">
31625
31751
  it('should remove the template directive and css class', function() {
@@ -33648,7 +33774,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
33648
33774
  * If the validity changes to invalid, the model will be set to `undefined`,
33649
33775
  * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`.
33650
33776
  * If the validity changes to valid, it will set the model to the last available valid
33651
- * modelValue, i.e. either the last parsed value or the last value set from the scope.
33777
+ * `$modelValue`, i.e. either the last parsed value or the last value set from the scope.
33652
33778
  */
33653
33779
  this.$validate = function() {
33654
33780
  // ignore $validate before model is initialized
@@ -34140,10 +34266,11 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
34140
34266
  var _name = 'Brian';
34141
34267
  $scope.user = {
34142
34268
  name: function(newName) {
34143
- if (angular.isDefined(newName)) {
34144
- _name = newName;
34145
- }
34146
- return _name;
34269
+ // Note that newName can be undefined for two reasons:
34270
+ // 1. Because it is called as a getter and thus called with no arguments
34271
+ // 2. Because the property should actually be set to undefined. This happens e.g. if the
34272
+ // input is invalid
34273
+ return arguments.length ? (_name = newName) : _name;
34147
34274
  }
34148
34275
  };
34149
34276
  }]);
@@ -34357,7 +34484,11 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
34357
34484
  var _name = 'Brian';
34358
34485
  $scope.user = {
34359
34486
  name: function(newName) {
34360
- return angular.isDefined(newName) ? (_name = newName) : _name;
34487
+ // Note that newName can be undefined for two reasons:
34488
+ // 1. Because it is called as a getter and thus called with no arguments
34489
+ // 2. Because the property should actually be set to undefined. This happens e.g. if the
34490
+ // input is invalid
34491
+ return arguments.length ? (_name = newName) : _name;
34361
34492
  }
34362
34493
  };
34363
34494
  }]);
@@ -34557,11 +34688,21 @@ var ngOptionsMinErr = minErr('ngOptions');
34557
34688
  * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
34558
34689
  * option. See example below for demonstration.
34559
34690
  *
34560
- * <div class="alert alert-warning">
34561
- * **Note:** By default, `ngModel` compares by reference, not value. This is important when binding to an
34562
- * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/). When using `track by`
34563
- * in an `ngOptions` expression, however, deep equality checks will be performed.
34564
- * </div>
34691
+ * ## Complex Models (objects or collections)
34692
+ *
34693
+ * **Note:** By default, `ngModel` watches the model by reference, not value. This is important when
34694
+ * binding any input directive to a model that is an object or a collection.
34695
+ *
34696
+ * Since this is a common situation for `ngOptions` the directive additionally watches the model using
34697
+ * `$watchCollection` when the select has the `multiple` attribute or when there is a `track by` clause in
34698
+ * the options expression. This allows ngOptions to trigger a re-rendering of the options even if the actual
34699
+ * object/collection has not changed identity but only a property on the object or an item in the collection
34700
+ * changes.
34701
+ *
34702
+ * Note that `$watchCollection` does a shallow comparison of the properties of the object (or the items in the collection
34703
+ * if the model is an array). This means that changing a property deeper inside the object/collection that the
34704
+ * first level will not trigger a re-rendering.
34705
+ *
34565
34706
  *
34566
34707
  * ## `select` **`as`**
34567
34708
  *
@@ -34777,9 +34918,13 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
34777
34918
  // Get the value by which we are going to track the option
34778
34919
  // if we have a trackFn then use that (passing scope and locals)
34779
34920
  // otherwise just hash the given viewValue
34780
- var getTrackByValue = trackBy ?
34781
- function(viewValue, locals) { return trackByFn(scope, locals); } :
34782
- function getHashOfValue(viewValue) { return hashKey(viewValue); };
34921
+ var getTrackByValueFn = trackBy ?
34922
+ function(value, locals) { return trackByFn(scope, locals); } :
34923
+ function getHashOfValue(value) { return hashKey(value); };
34924
+ var getTrackByValue = function(value, key) {
34925
+ return getTrackByValueFn(value, getLocals(value, key));
34926
+ };
34927
+
34783
34928
  var displayFn = $parse(match[2] || match[1]);
34784
34929
  var groupByFn = $parse(match[3] || '');
34785
34930
  var disableWhenFn = $parse(match[4] || '');
@@ -34806,6 +34951,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
34806
34951
 
34807
34952
  return {
34808
34953
  trackBy: trackBy,
34954
+ getTrackByValue: getTrackByValue,
34809
34955
  getWatchables: $parse(valuesFn, function(values) {
34810
34956
  // Create a collection of things that we would like to watch (watchedArray)
34811
34957
  // so that they can all be watched using a single $watchCollection
@@ -34815,11 +34961,11 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
34815
34961
 
34816
34962
  Object.keys(values).forEach(function getWatchable(key) {
34817
34963
  var locals = getLocals(values[key], key);
34818
- var selectValue = getTrackByValue(values[key], locals);
34964
+ var selectValue = getTrackByValueFn(values[key], locals);
34819
34965
  watchedArray.push(selectValue);
34820
34966
 
34821
34967
  // Only need to watch the displayFn if there is a specific label expression
34822
- if (match[2]) {
34968
+ if (match[2] || match[1]) {
34823
34969
  var label = displayFn(scope, locals);
34824
34970
  watchedArray.push(label);
34825
34971
  }
@@ -34841,17 +34987,29 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
34841
34987
  // The option values were already computed in the `getWatchables` fn,
34842
34988
  // which must have been called to trigger `getOptions`
34843
34989
  var optionValues = valuesFn(scope) || [];
34990
+ var optionValuesKeys;
34844
34991
 
34845
- var keys = Object.keys(optionValues);
34846
- keys.forEach(function getOption(key) {
34847
34992
 
34848
- // Ignore "angular" properties that start with $ or $$
34849
- if (key.charAt(0) === '$') return;
34993
+ if (!keyName && isArrayLike(optionValues)) {
34994
+ optionValuesKeys = optionValues;
34995
+ } else {
34996
+ // if object, extract keys, in enumeration order, unsorted
34997
+ optionValuesKeys = [];
34998
+ for (var itemKey in optionValues) {
34999
+ if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {
35000
+ optionValuesKeys.push(itemKey);
35001
+ }
35002
+ }
35003
+ }
35004
+
35005
+ var optionValuesLength = optionValuesKeys.length;
34850
35006
 
35007
+ for (var index = 0; index < optionValuesLength; index++) {
35008
+ var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index];
34851
35009
  var value = optionValues[key];
34852
35010
  var locals = getLocals(value, key);
34853
35011
  var viewValue = viewValueFn(scope, locals);
34854
- var selectValue = getTrackByValue(viewValue, locals);
35012
+ var selectValue = getTrackByValueFn(viewValue, locals);
34855
35013
  var label = displayFn(scope, locals);
34856
35014
  var group = groupByFn(scope, locals);
34857
35015
  var disabled = disableWhenFn(scope, locals);
@@ -34859,13 +35017,13 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
34859
35017
 
34860
35018
  optionItems.push(optionItem);
34861
35019
  selectValueMap[selectValue] = optionItem;
34862
- });
35020
+ }
34863
35021
 
34864
35022
  return {
34865
35023
  items: optionItems,
34866
35024
  selectValueMap: selectValueMap,
34867
35025
  getOptionFromViewValue: function(value) {
34868
- return selectValueMap[getTrackByValue(value, getLocals(value))];
35026
+ return selectValueMap[getTrackByValue(value)];
34869
35027
  },
34870
35028
  getViewValueFromOption: function(option) {
34871
35029
  // If the viewValue could be an object that may be mutated by the application,
@@ -34943,44 +35101,54 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
34943
35101
  };
34944
35102
 
34945
35103
 
34946
- selectCtrl.writeValue = function writeNgOptionsValue(value) {
34947
- var option = options.getOptionFromViewValue(value);
35104
+ // Update the controller methods for multiple selectable options
35105
+ if (!multiple) {
34948
35106
 
34949
- if (option && !option.disabled) {
34950
- if (selectElement[0].value !== option.selectValue) {
34951
- removeUnknownOption();
34952
- removeEmptyOption();
35107
+ selectCtrl.writeValue = function writeNgOptionsValue(value) {
35108
+ var option = options.getOptionFromViewValue(value);
34953
35109
 
34954
- selectElement[0].value = option.selectValue;
34955
- option.element.selected = true;
34956
- option.element.setAttribute('selected', 'selected');
34957
- }
34958
- } else {
34959
- if (value === null || providedEmptyOption) {
34960
- removeUnknownOption();
34961
- renderEmptyOption();
35110
+ if (option && !option.disabled) {
35111
+ if (selectElement[0].value !== option.selectValue) {
35112
+ removeUnknownOption();
35113
+ removeEmptyOption();
35114
+
35115
+ selectElement[0].value = option.selectValue;
35116
+ option.element.selected = true;
35117
+ option.element.setAttribute('selected', 'selected');
35118
+ }
34962
35119
  } else {
34963
- removeEmptyOption();
34964
- renderUnknownOption();
35120
+ if (value === null || providedEmptyOption) {
35121
+ removeUnknownOption();
35122
+ renderEmptyOption();
35123
+ } else {
35124
+ removeEmptyOption();
35125
+ renderUnknownOption();
35126
+ }
34965
35127
  }
34966
- }
34967
- };
35128
+ };
34968
35129
 
34969
- selectCtrl.readValue = function readNgOptionsValue() {
35130
+ selectCtrl.readValue = function readNgOptionsValue() {
34970
35131
 
34971
- var selectedOption = options.selectValueMap[selectElement.val()];
35132
+ var selectedOption = options.selectValueMap[selectElement.val()];
34972
35133
 
34973
- if (selectedOption && !selectedOption.disabled) {
34974
- removeEmptyOption();
34975
- removeUnknownOption();
34976
- return options.getViewValueFromOption(selectedOption);
34977
- }
34978
- return null;
34979
- };
35134
+ if (selectedOption && !selectedOption.disabled) {
35135
+ removeEmptyOption();
35136
+ removeUnknownOption();
35137
+ return options.getViewValueFromOption(selectedOption);
35138
+ }
35139
+ return null;
35140
+ };
34980
35141
 
35142
+ // If we are using `track by` then we must watch the tracked value on the model
35143
+ // since ngModel only watches for object identity change
35144
+ if (ngOptions.trackBy) {
35145
+ scope.$watch(
35146
+ function() { return ngOptions.getTrackByValue(ngModelCtrl.$viewValue); },
35147
+ function() { ngModelCtrl.$render(); }
35148
+ );
35149
+ }
34981
35150
 
34982
- // Update the controller methods for multiple selectable options
34983
- if (multiple) {
35151
+ } else {
34984
35152
 
34985
35153
  ngModelCtrl.$isEmpty = function(value) {
34986
35154
  return !value || value.length === 0;
@@ -35012,6 +35180,22 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
35012
35180
 
35013
35181
  return selections;
35014
35182
  };
35183
+
35184
+ // If we are using `track by` then we must watch these tracked values on the model
35185
+ // since ngModel only watches for object identity change
35186
+ if (ngOptions.trackBy) {
35187
+
35188
+ scope.$watchCollection(function() {
35189
+ if (isArray(ngModelCtrl.$viewValue)) {
35190
+ return ngModelCtrl.$viewValue.map(function(value) {
35191
+ return ngOptions.getTrackByValue(value);
35192
+ });
35193
+ }
35194
+ }, function() {
35195
+ ngModelCtrl.$render();
35196
+ });
35197
+
35198
+ }
35015
35199
  }
35016
35200
 
35017
35201
 
@@ -35038,11 +35222,6 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
35038
35222
  // We will re-render the option elements if the option values or labels change
35039
35223
  scope.$watchCollection(ngOptions.getWatchables, updateOptions);
35040
35224
 
35041
- // We also need to watch to see if the internals of the model changes, since
35042
- // ngModel only watches for object identity change
35043
- if (ngOptions.trackBy) {
35044
- scope.$watch(attr.ngModel, function() { ngModelCtrl.$render(); }, true);
35045
- }
35046
35225
  // ------------------------------------------------------------------ //
35047
35226
 
35048
35227
 
@@ -36386,7 +36565,7 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
36386
36565
  *
36387
36566
  * @scope
36388
36567
  * @priority 1200
36389
- * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.
36568
+ * @param {*} ngSwitch|on expression to match against <code>ng-switch-when</code>.
36390
36569
  * On child elements add:
36391
36570
  *
36392
36571
  * * `ngSwitchWhen`: the case statement to match against. If match then this
@@ -36403,7 +36582,7 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
36403
36582
  <div ng-controller="ExampleController">
36404
36583
  <select ng-model="selection" ng-options="item for item in items">
36405
36584
  </select>
36406
- <tt>selection={{selection}}</tt>
36585
+ <code>selection={{selection}}</code>
36407
36586
  <hr/>
36408
36587
  <div class="animate-switch-container"
36409
36588
  ng-switch on="selection">
@@ -36794,12 +36973,6 @@ var SelectController =
36794
36973
  * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
36795
36974
  * option. See example below for demonstration.
36796
36975
  *
36797
- * <div class="alert alert-warning">
36798
- * **Note:** By default, `ngModel` compares by reference, not value. This is important when binding to an
36799
- * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/). When using `track by`
36800
- * in an `ngOptions` expression, however, deep equality checks will be performed.
36801
- * </div>
36802
- *
36803
36976
  */
36804
36977
  var selectDirective = function() {
36805
36978
 
@@ -39276,5 +39449,5 @@ if (config.autotest) {
39276
39449
  })(window, document);
39277
39450
 
39278
39451
 
39279
- !window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";\n\n[ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\n.ng-cloak, .x-ng-cloak,\n.ng-hide:not(.ng-hide-animate) {\n display: none !important;\n}\n\nng\\:form {\n display: block;\n}\n\n.ng-animate-shim {\n visibility:hidden;\n}\n\n.ng-animate-anchor {\n position:absolute;\n}\n</style>');
39452
+ !window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";\n\n[ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\n.ng-cloak, .x-ng-cloak,\n.ng-hide:not(.ng-hide-animate) {\n display: none !important;\n}\n\nng\\:form {\n display: block;\n}\n\n.ng-animate-shim {\n visibility:hidden;\n}\n\n.ng-anchor {\n position:absolute;\n}\n</style>');
39280
39453
  !window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";\n/* CSS Document */\n\n/** Structure */\nbody {\n font-family: Arial, sans-serif;\n margin: 0;\n font-size: 14px;\n}\n\n#system-error {\n font-size: 1.5em;\n text-align: center;\n}\n\n#json, #xml {\n display: none;\n}\n\n#header {\n position: fixed;\n width: 100%;\n}\n\n#specs {\n padding-top: 50px;\n}\n\n#header .angular {\n font-family: Courier New, monospace;\n font-weight: bold;\n}\n\n#header h1 {\n font-weight: normal;\n float: left;\n font-size: 30px;\n line-height: 30px;\n margin: 0;\n padding: 10px 10px;\n height: 30px;\n}\n\n#application h2,\n#specs h2 {\n margin: 0;\n padding: 0.5em;\n font-size: 1.1em;\n}\n\n#status-legend {\n margin-top: 10px;\n margin-right: 10px;\n}\n\n#header,\n#application,\n.test-info,\n.test-actions li {\n overflow: hidden;\n}\n\n#application {\n margin: 10px;\n}\n\n#application iframe {\n width: 100%;\n height: 758px;\n}\n\n#application .popout {\n float: right;\n}\n\n#application iframe {\n border: none;\n}\n\n.tests li,\n.test-actions li,\n.test-it li,\n.test-it ol,\n.status-display {\n list-style-type: none;\n}\n\n.tests,\n.test-it ol,\n.status-display {\n margin: 0;\n padding: 0;\n}\n\n.test-info {\n margin-left: 1em;\n margin-top: 0.5em;\n border-radius: 8px 0 0 8px;\n -webkit-border-radius: 8px 0 0 8px;\n -moz-border-radius: 8px 0 0 8px;\n cursor: pointer;\n}\n\n.test-info:hover .test-name {\n text-decoration: underline;\n}\n\n.test-info .closed:before {\n content: \'\\25b8\\00A0\';\n}\n\n.test-info .open:before {\n content: \'\\25be\\00A0\';\n font-weight: bold;\n}\n\n.test-it ol {\n margin-left: 2.5em;\n}\n\n.status-display,\n.status-display li {\n float: right;\n}\n\n.status-display li {\n padding: 5px 10px;\n}\n\n.timer-result,\n.test-title {\n display: inline-block;\n margin: 0;\n padding: 4px;\n}\n\n.test-actions .test-title,\n.test-actions .test-result {\n display: table-cell;\n padding-left: 0.5em;\n padding-right: 0.5em;\n}\n\n.test-actions {\n display: table;\n}\n\n.test-actions li {\n display: table-row;\n}\n\n.timer-result {\n width: 4em;\n padding: 0 10px;\n text-align: right;\n font-family: monospace;\n}\n\n.test-it pre,\n.test-actions pre {\n clear: left;\n color: black;\n margin-left: 6em;\n}\n\n.test-describe {\n padding-bottom: 0.5em;\n}\n\n.test-describe .test-describe {\n margin: 5px 5px 10px 2em;\n}\n\n.test-actions .status-pending .test-title:before {\n content: \'\\00bb\\00A0\';\n}\n\n.scrollpane {\n max-height: 20em;\n overflow: auto;\n}\n\n/** Colors */\n\n#header {\n background-color: #F2C200;\n}\n\n#specs h2 {\n border-top: 2px solid #BABAD1;\n}\n\n#specs h2,\n#application h2 {\n background-color: #efefef;\n}\n\n#application {\n border: 1px solid #BABAD1;\n}\n\n.test-describe .test-describe {\n border-left: 1px solid #BABAD1;\n border-right: 1px solid #BABAD1;\n border-bottom: 1px solid #BABAD1;\n}\n\n.status-display {\n border: 1px solid #777;\n}\n\n.status-display .status-pending,\n.status-pending .test-info {\n background-color: #F9EEBC;\n}\n\n.status-display .status-success,\n.status-success .test-info {\n background-color: #B1D7A1;\n}\n\n.status-display .status-failure,\n.status-failure .test-info {\n background-color: #FF8286;\n}\n\n.status-display .status-error,\n.status-error .test-info {\n background-color: black;\n color: white;\n}\n\n.test-actions .status-success .test-title {\n color: #30B30A;\n}\n\n.test-actions .status-failure .test-title {\n color: #DF0000;\n}\n\n.test-actions .status-error .test-title {\n color: black;\n}\n\n.test-actions .timer-result {\n color: #888;\n}\n</style>');