angularjs-rails 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  module AngularJS
2
2
  module Rails
3
- VERSION = "1.0.3"
3
+ VERSION = "1.0.4"
4
4
  end
5
5
  end
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.3
2
+ * @license AngularJS v1.0.4
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -10,10 +10,10 @@ var directive = {};
10
10
  var service = { value: {} };
11
11
 
12
12
  var DEPENDENCIES = {
13
- 'angular.js': 'http://code.angularjs.org/angular-' + angular.version.full + '.min.js',
14
- 'angular-resource.js': 'http://code.angularjs.org/angular-resource-' + angular.version.full + '.min.js',
15
- 'angular-sanitize.js': 'http://code.angularjs.org/angular-sanitize-' + angular.version.full + '.min.js',
16
- 'angular-cookies.js': 'http://code.angularjs.org/angular-cookies-' + angular.version.full + '.min.js'
13
+ 'angular.js': 'http://code.angularjs.org/' + angular.version.full + 'angular.min.js',
14
+ 'angular-resource.js': 'http://code.angularjs.org/' + angular.version.full + 'angular-resource.min.js',
15
+ 'angular-sanitize.js': 'http://code.angularjs.org/' + angular.version.full + 'angular-sanitize.min.js',
16
+ 'angular-cookies.js': 'http://code.angularjs.org/' + angular.version.full + 'angular-cookies.min.js'
17
17
  };
18
18
 
19
19
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.3
2
+ * @license AngularJS v1.0.4
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.3
2
+ * @license AngularJS v1.0.4
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.3
2
+ * @license AngularJS v1.0.4
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,6 +1,5 @@
1
-
2
1
  /**
3
- * @license AngularJS v1.0.3
2
+ * @license AngularJS v1.0.4
4
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
5
4
  * License: MIT
6
5
  *
@@ -203,6 +202,30 @@ angular.mock.$Browser.prototype = {
203
202
  * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed
204
203
  * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration
205
204
  * information.
205
+ *
206
+ *
207
+ * <pre>
208
+ * describe('$exceptionHandlerProvider', function() {
209
+ *
210
+ * it('should capture log messages and exceptions', function() {
211
+ *
212
+ * module(function($exceptionHandlerProvider) {
213
+ * $exceptionHandlerProvider.mode('log');
214
+ * });
215
+ *
216
+ * inject(function($log, $exceptionHandler, $timeout) {
217
+ * $timeout(function() { $log.log(1); });
218
+ * $timeout(function() { $log.log(2); throw 'banana peel'; });
219
+ * $timeout(function() { $log.log(3); });
220
+ * expect($exceptionHandler.errors).toEqual([]);
221
+ * expect($log.assertEmpty());
222
+ * $timeout.flush();
223
+ * expect($exceptionHandler.errors).toEqual(['banana peel']);
224
+ * expect($log.log.logs).toEqual([[1], [2], [3]]);
225
+ * });
226
+ * });
227
+ * });
228
+ * </pre>
206
229
  */
207
230
 
208
231
  angular.mock.$ExceptionHandlerProvider = function() {
@@ -221,8 +244,8 @@ angular.mock.$ExceptionHandlerProvider = function() {
221
244
  * - `rethrow`: If any errors are are passed into the handler in tests, it typically
222
245
  * means that there is a bug in the application or test, so this mock will
223
246
  * make these tests fail.
224
- * - `log`: Sometimes it is desirable to test that an error is throw, for this case the `log` mode stores the
225
- * error and allows later assertion of it.
247
+ * - `log`: Sometimes it is desirable to test that an error is throw, for this case the `log` mode stores an
248
+ * array of errors in `$exceptionHandler.errors`, to allow later assertion of them.
226
249
  * See {@link ngMock.$log#assertEmpty assertEmpty()} and
227
250
  * {@link ngMock.$log#reset reset()}
228
251
  */
@@ -562,7 +585,7 @@ angular.mock.$LogProvider = function() {
562
585
 
563
586
  /**
564
587
  * @ngdoc function
565
- * @name angular.mock.debug
588
+ * @name angular.mock.dump
566
589
  * @description
567
590
  *
568
591
  * *NOTE*: this is not an injectable instance, just a globally available function.
@@ -745,7 +768,7 @@ angular.mock.dump = function(object) {
745
768
  }
746
769
 
747
770
  // testing controller
748
- var $http;
771
+ var $httpBackend;
749
772
 
750
773
  beforeEach(inject(function($injector) {
751
774
  $httpBackend = $injector.get('$httpBackend');
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.3
2
+ * @license AngularJS v1.0.4
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -12,7 +12,7 @@
12
12
  * @description
13
13
  */
14
14
 
15
- /**
15
+ /**
16
16
  * @ngdoc object
17
17
  * @name ngResource.$resource
18
18
  * @requires $http
@@ -25,7 +25,9 @@
25
25
  * the need to interact with the low level {@link ng.$http $http} service.
26
26
  *
27
27
  * @param {string} url A parameterized URL template with parameters prefixed by `:` as in
28
- * `/user/:username`.
28
+ * `/user/:username`. If you are using a URL with a port number (e.g.
29
+ * `http://example.com:8080/api`), you'll need to escape the colon character before the port
30
+ * number, like this: `$resource('http://example.com\\:8080/api')`.
29
31
  *
30
32
  * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
31
33
  * `actions` methods.
@@ -230,46 +232,46 @@ angular.module('ngResource', ['ng']).
230
232
  return $parse(path)(obj);
231
233
  };
232
234
 
233
- /**
234
- * We need our custom mehtod because encodeURIComponent is too aggressive and doesn't follow
235
- * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
236
- * segments:
237
- * segment = *pchar
238
- * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
239
- * pct-encoded = "%" HEXDIG HEXDIG
240
- * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
241
- * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
242
- * / "*" / "+" / "," / ";" / "="
243
- */
244
- function encodeUriSegment(val) {
245
- return encodeUriQuery(val, true).
246
- replace(/%26/gi, '&').
247
- replace(/%3D/gi, '=').
248
- replace(/%2B/gi, '+');
249
- }
250
-
251
-
252
- /**
253
- * This method is intended for encoding *key* or *value* parts of query component. We need a custom
254
- * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be
255
- * encoded per http://tools.ietf.org/html/rfc3986:
256
- * query = *( pchar / "/" / "?" )
257
- * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
258
- * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
259
- * pct-encoded = "%" HEXDIG HEXDIG
260
- * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
261
- * / "*" / "+" / "," / ";" / "="
262
- */
263
- function encodeUriQuery(val, pctEncodeSpaces) {
264
- return encodeURIComponent(val).
265
- replace(/%40/gi, '@').
266
- replace(/%3A/gi, ':').
267
- replace(/%24/g, '$').
268
- replace(/%2C/gi, ',').
269
- replace((pctEncodeSpaces ? null : /%20/g), '+');
270
- }
271
-
272
- function Route(template, defaults) {
235
+ /**
236
+ * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
237
+ * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
238
+ * segments:
239
+ * segment = *pchar
240
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
241
+ * pct-encoded = "%" HEXDIG HEXDIG
242
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
243
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
244
+ * / "*" / "+" / "," / ";" / "="
245
+ */
246
+ function encodeUriSegment(val) {
247
+ return encodeUriQuery(val, true).
248
+ replace(/%26/gi, '&').
249
+ replace(/%3D/gi, '=').
250
+ replace(/%2B/gi, '+');
251
+ }
252
+
253
+
254
+ /**
255
+ * This method is intended for encoding *key* or *value* parts of query component. We need a custom
256
+ * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be
257
+ * encoded per http://tools.ietf.org/html/rfc3986:
258
+ * query = *( pchar / "/" / "?" )
259
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
260
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
261
+ * pct-encoded = "%" HEXDIG HEXDIG
262
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
263
+ * / "*" / "+" / "," / ";" / "="
264
+ */
265
+ function encodeUriQuery(val, pctEncodeSpaces) {
266
+ return encodeURIComponent(val).
267
+ replace(/%40/gi, '@').
268
+ replace(/%3A/gi, ':').
269
+ replace(/%24/g, '$').
270
+ replace(/%2C/gi, ',').
271
+ replace((pctEncodeSpaces ? null : /%20/g), '+');
272
+ }
273
+
274
+ function Route(template, defaults) {
273
275
  this.template = template = template + '#';
274
276
  this.defaults = defaults || {};
275
277
  var urlParams = this.urlParams = {};
@@ -295,7 +297,14 @@ angular.module('ngResource', ['ng']).
295
297
  encodedVal = encodeUriSegment(val);
296
298
  url = url.replace(new RegExp(":" + urlParam + "(\\W)", "g"), encodedVal + "$1");
297
299
  } else {
298
- url = url.replace(new RegExp("/?:" + urlParam + "(\\W)", "g"), '$1');
300
+ url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W)", "g"), function(match,
301
+ leadingSlashes, tail) {
302
+ if (tail.charAt(0) == '/') {
303
+ return tail;
304
+ } else {
305
+ return leadingSlashes + tail;
306
+ }
307
+ });
299
308
  }
300
309
  });
301
310
  url = url.replace(/\/?#$/, '');
@@ -331,6 +340,7 @@ angular.module('ngResource', ['ng']).
331
340
  }
332
341
 
333
342
  forEach(actions, function(action, name) {
343
+ action.method = angular.uppercase(action.method);
334
344
  var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';
335
345
  Resource[name] = function(a1, a2, a3, a4) {
336
346
  var params = {};
@@ -396,11 +406,6 @@ angular.module('ngResource', ['ng']).
396
406
  };
397
407
 
398
408
 
399
- Resource.bind = function(additionalParamDefaults){
400
- return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
401
- };
402
-
403
-
404
409
  Resource.prototype['$' + name] = function(a1, a2, a3) {
405
410
  var params = extractParams(this),
406
411
  success = noop,
@@ -426,6 +431,11 @@ angular.module('ngResource', ['ng']).
426
431
  Resource[name].call(this, params, data, success, error);
427
432
  };
428
433
  });
434
+
435
+ Resource.bind = function(additionalParamDefaults){
436
+ return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
437
+ };
438
+
429
439
  return Resource;
430
440
  }
431
441
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.3
2
+ * @license AngularJS v1.0.4
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -9404,7 +9404,7 @@ if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
9404
9404
 
9405
9405
  })( window );
9406
9406
  /**
9407
- * @license AngularJS v1.0.3
9407
+ * @license AngularJS v1.0.4
9408
9408
  * (c) 2010-2012 Google, Inc. http://angularjs.org
9409
9409
  * License: MIT
9410
9410
  */
@@ -10032,13 +10032,15 @@ function equals(o1, o2) {
10032
10032
  if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;
10033
10033
  keySet = {};
10034
10034
  for(key in o1) {
10035
- if (key.charAt(0) !== '$' && !isFunction(o1[key]) && !equals(o1[key], o2[key])) {
10036
- return false;
10037
- }
10035
+ if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
10036
+ if (!equals(o1[key], o2[key])) return false;
10038
10037
  keySet[key] = true;
10039
10038
  }
10040
10039
  for(key in o2) {
10041
- if (!keySet[key] && key.charAt(0) !== '$' && !isFunction(o2[key])) return false;
10040
+ if (!keySet[key] &&
10041
+ key.charAt(0) !== '$' &&
10042
+ o2[key] !== undefined &&
10043
+ !isFunction(o2[key])) return false;
10042
10044
  }
10043
10045
  return true;
10044
10046
  }
@@ -10652,11 +10654,11 @@ function setupModuleLoader(window) {
10652
10654
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
10653
10655
  */
10654
10656
  var version = {
10655
- full: '1.0.3', // all of these placeholder strings will be replaced by rake's
10657
+ full: '1.0.4', // all of these placeholder strings will be replaced by rake's
10656
10658
  major: 1, // compile task
10657
10659
  minor: 0,
10658
- dot: 3,
10659
- codeName: 'bouncy-thunder'
10660
+ dot: 4,
10661
+ codeName: 'bewildering-hair'
10660
10662
  };
10661
10663
 
10662
10664
 
@@ -10828,7 +10830,7 @@ function publishExternalAPI(angular){
10828
10830
  * - [val()](http://api.jquery.com/val/)
10829
10831
  * - [wrap()](http://api.jquery.com/wrap/)
10830
10832
  *
10831
- * ## In addtion to the above, Angular privides an additional method to both jQuery and jQuery lite:
10833
+ * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:
10832
10834
  *
10833
10835
  * - `controller(name)` - retrieves the controller of the current element or its parent. By default
10834
10836
  * retrieves controller associated with the `ngController` directive. If `name` is provided as
@@ -11416,14 +11418,14 @@ forEach({
11416
11418
  children: function(element) {
11417
11419
  var children = [];
11418
11420
  forEach(element.childNodes, function(element){
11419
- if (element.nodeName != '#text')
11421
+ if (element.nodeType === 1)
11420
11422
  children.push(element);
11421
11423
  });
11422
11424
  return children;
11423
11425
  },
11424
11426
 
11425
11427
  contents: function(element) {
11426
- return element.childNodes;
11428
+ return element.childNodes || [];
11427
11429
  },
11428
11430
 
11429
11431
  append: function(element, node) {
@@ -11486,7 +11488,16 @@ forEach({
11486
11488
  },
11487
11489
 
11488
11490
  next: function(element) {
11489
- return element.nextSibling;
11491
+ if (element.nextElementSibling) {
11492
+ return element.nextElementSibling;
11493
+ }
11494
+
11495
+ // IE8 doesn't have nextElementSibling
11496
+ var elm = element.nextSibling;
11497
+ while (elm != null && elm.nodeType !== 1) {
11498
+ elm = elm.nextSibling;
11499
+ }
11500
+ return elm;
11490
11501
  },
11491
11502
 
11492
11503
  find: function(element, selector) {
@@ -12072,7 +12083,7 @@ function createInjector(modulesToLoad) {
12072
12083
  }
12073
12084
 
12074
12085
  function provider(name, provider_) {
12075
- if (isFunction(provider_)) {
12086
+ if (isFunction(provider_) || isArray(provider_)) {
12076
12087
  provider_ = providerInjector.instantiate(provider_);
12077
12088
  }
12078
12089
  if (!provider_.$get) {
@@ -12189,7 +12200,7 @@ function createInjector(modulesToLoad) {
12189
12200
  args.push(
12190
12201
  locals && locals.hasOwnProperty(key)
12191
12202
  ? locals[key]
12192
- : getService(key, path)
12203
+ : getService(key)
12193
12204
  );
12194
12205
  }
12195
12206
  if (!fn.$inject) {
@@ -12289,7 +12300,7 @@ function $AnchorScrollProvider() {
12289
12300
  }
12290
12301
 
12291
12302
  // does not scroll when user clicks on anchor link that is currently on
12292
- // (no url change, no $locaiton.hash() change), browser native does scroll
12303
+ // (no url change, no $location.hash() change), browser native does scroll
12293
12304
  if (autoScrollingEnabled) {
12294
12305
  $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
12295
12306
  function autoScrollWatchAction() {
@@ -12577,14 +12588,15 @@ function Browser(window, document, $log, $sniffer) {
12577
12588
  } else {
12578
12589
  if (isString(value)) {
12579
12590
  cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;
12591
+
12592
+ // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
12593
+ // - 300 cookies
12594
+ // - 20 cookies per unique domain
12595
+ // - 4096 bytes per cookie
12580
12596
  if (cookieLength > 4096) {
12581
12597
  $log.warn("Cookie '"+ name +"' possibly not set or overflowed because it was too large ("+
12582
12598
  cookieLength + " > 4096 bytes)!");
12583
12599
  }
12584
- if (lastCookies.length > 20) {
12585
- $log.warn("Cookie '"+ name +"' possibly not set or overflowed because too many cookies " +
12586
- "were already set (" + lastCookies.length + " > 20 )");
12587
- }
12588
12600
  }
12589
12601
  }
12590
12602
  } else {
@@ -13150,7 +13162,7 @@ function $CompileProvider($provide) {
13150
13162
  // We can not compile top level text elements since text nodes can be merged and we will
13151
13163
  // not be able to attach scope data to them, so we will wrap them in <span>
13152
13164
  forEach($compileNodes, function(node, index){
13153
- if (node.nodeType == 3 /* text node */) {
13165
+ if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\S+/) /* non-empty */ ) {
13154
13166
  $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
13155
13167
  }
13156
13168
  });
@@ -13199,68 +13211,74 @@ function $CompileProvider($provide) {
13199
13211
  * @returns {?function} A composite linking function of all of the matched directives or null.
13200
13212
  */
13201
13213
  function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {
13202
- var linkFns = [],
13203
- nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;
13214
+ var linkFns = [],
13215
+ nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;
13204
13216
 
13205
- for(var i = 0; i < nodeList.length; i++) {
13206
- attrs = new Attributes();
13217
+ for(var i = 0; i < nodeList.length; i++) {
13218
+ attrs = new Attributes();
13207
13219
 
13208
- // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
13209
- directives = collectDirectives(nodeList[i], [], attrs, maxPriority);
13220
+ // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
13221
+ directives = collectDirectives(nodeList[i], [], attrs, maxPriority);
13210
13222
 
13211
- nodeLinkFn = (directives.length)
13212
- ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)
13213
- : null;
13223
+ nodeLinkFn = (directives.length)
13224
+ ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)
13225
+ : null;
13214
13226
 
13215
- childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)
13216
- ? null
13217
- : compileNodes(nodeList[i].childNodes,
13218
- nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
13227
+ childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)
13228
+ ? null
13229
+ : compileNodes(nodeList[i].childNodes,
13230
+ nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
13219
13231
 
13220
- linkFns.push(nodeLinkFn);
13221
- linkFns.push(childLinkFn);
13222
- linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);
13223
- }
13232
+ linkFns.push(nodeLinkFn);
13233
+ linkFns.push(childLinkFn);
13234
+ linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);
13235
+ }
13224
13236
 
13225
- // return a linking function if we have found anything, null otherwise
13226
- return linkFnFound ? compositeLinkFn : null;
13237
+ // return a linking function if we have found anything, null otherwise
13238
+ return linkFnFound ? compositeLinkFn : null;
13227
13239
 
13228
- function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
13229
- var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn;
13240
+ function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
13241
+ var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;
13230
13242
 
13231
- for(var i = 0, n = 0, ii = linkFns.length; i < ii; n++) {
13232
- node = nodeList[n];
13233
- nodeLinkFn = linkFns[i++];
13234
- childLinkFn = linkFns[i++];
13243
+ // copy nodeList so that linking doesn't break due to live list updates.
13244
+ var stableNodeList = [];
13245
+ for (i = 0, ii = nodeList.length; i < ii; i++) {
13246
+ stableNodeList.push(nodeList[i]);
13247
+ }
13235
13248
 
13236
- if (nodeLinkFn) {
13237
- if (nodeLinkFn.scope) {
13238
- childScope = scope.$new(isObject(nodeLinkFn.scope));
13239
- jqLite(node).data('$scope', childScope);
13240
- } else {
13241
- childScope = scope;
13242
- }
13243
- childTranscludeFn = nodeLinkFn.transclude;
13244
- if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {
13245
- nodeLinkFn(childLinkFn, childScope, node, $rootElement,
13246
- (function(transcludeFn) {
13247
- return function(cloneFn) {
13248
- var transcludeScope = scope.$new();
13249
-
13250
- return transcludeFn(transcludeScope, cloneFn).
13251
- bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));
13249
+ for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {
13250
+ node = stableNodeList[n];
13251
+ nodeLinkFn = linkFns[i++];
13252
+ childLinkFn = linkFns[i++];
13253
+
13254
+ if (nodeLinkFn) {
13255
+ if (nodeLinkFn.scope) {
13256
+ childScope = scope.$new(isObject(nodeLinkFn.scope));
13257
+ jqLite(node).data('$scope', childScope);
13258
+ } else {
13259
+ childScope = scope;
13260
+ }
13261
+ childTranscludeFn = nodeLinkFn.transclude;
13262
+ if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {
13263
+ nodeLinkFn(childLinkFn, childScope, node, $rootElement,
13264
+ (function(transcludeFn) {
13265
+ return function(cloneFn) {
13266
+ var transcludeScope = scope.$new();
13267
+
13268
+ return transcludeFn(transcludeScope, cloneFn).
13269
+ bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));
13252
13270
  };
13253
13271
  })(childTranscludeFn || transcludeFn)
13254
- );
13255
- } else {
13256
- nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);
13257
- }
13258
- } else if (childLinkFn) {
13259
- childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
13260
- }
13261
- }
13262
- }
13263
- }
13272
+ );
13273
+ } else {
13274
+ nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);
13275
+ }
13276
+ } else if (childLinkFn) {
13277
+ childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
13278
+ }
13279
+ }
13280
+ }
13281
+ }
13264
13282
 
13265
13283
 
13266
13284
  /**
@@ -13407,7 +13425,7 @@ function $CompileProvider($provide) {
13407
13425
  if (directiveValue == 'element') {
13408
13426
  $template = jqLite(compileNode);
13409
13427
  $compileNode = templateAttrs.$$element =
13410
- jqLite('<!-- ' + directiveName + ': ' + templateAttrs[directiveName] + ' -->');
13428
+ jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));
13411
13429
  compileNode = $compileNode[0];
13412
13430
  replaceWith($rootElement, jqLite($template[0]), compileNode);
13413
13431
  childTranscludeFn = compile($template, transcludeFn, terminalPriority);
@@ -14072,11 +14090,12 @@ function $DocumentProvider(){
14072
14090
  * the browser console.
14073
14091
  *
14074
14092
  * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by
14075
- * {@link ngMock.$exceptionHandler mock $exceptionHandler}
14093
+ * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
14076
14094
  *
14077
14095
  * @param {Error} exception Exception associated with the error.
14078
14096
  * @param {string=} cause optional information about the context in which
14079
14097
  * the error was thrown.
14098
+ *
14080
14099
  */
14081
14100
  function $ExceptionHandlerProvider() {
14082
14101
  this.$get = ['$log', function($log){
@@ -15876,7 +15895,7 @@ function $ParseProvider() {
15876
15895
  * performed asynchronously, and may or may not be finished at any given point in time.
15877
15896
  *
15878
15897
  * From the perspective of dealing with error handling, deferred and promise apis are to
15879
- * asynchronous programing what `try`, `catch` and `throw` keywords are to synchronous programing.
15898
+ * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
15880
15899
  *
15881
15900
  * <pre>
15882
15901
  * // for the purpose of this example let's assume that variables `$q` and `scope` are
@@ -15986,6 +16005,30 @@ function $ParseProvider() {
15986
16005
  * you can treat promises attached to a scope as if they were the resulting values.
15987
16006
  * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains
15988
16007
  * all the important functionality needed for common async tasks.
16008
+ *
16009
+ * # Testing
16010
+ *
16011
+ * <pre>
16012
+ * it('should simulate promise', inject(function($q, $rootSCope) {
16013
+ * var deferred = $q.defer();
16014
+ * var promise = deferred.promise;
16015
+ * var resolvedValue;
16016
+ *
16017
+ * promise.then(function(value) { resolvedValue = value; });
16018
+ * expect(resolvedValue).toBeUndefined();
16019
+ *
16020
+ * // Simulate resolving of promise
16021
+ * defered.resolve(123);
16022
+ * // Note that the 'then' function does not get called synchronously.
16023
+ * // This is because we want the promise API to always be async, whether or not
16024
+ * // it got called synchronously or asynchronously.
16025
+ * expect(resolvedValue).toBeUndefined();
16026
+ *
16027
+ * // Propagate promise resolution to 'then' functions using $apply().
16028
+ * $rootScope.$apply();
16029
+ * expect(resolvedValue).toEqual(123);
16030
+ * });
16031
+ * </pre>
15989
16032
  */
15990
16033
  function $QProvider() {
15991
16034
 
@@ -16272,8 +16315,13 @@ function $RouteProvider(){
16272
16315
  *
16273
16316
  * @param {string} path Route path (matched against `$location.path`). If `$location.path`
16274
16317
  * contains redundant trailing slash or is missing one, the route will still match and the
16275
- * `$location.path` will be updated to add or drop the trailing slash to exacly match the
16318
+ * `$location.path` will be updated to add or drop the trailing slash to exactly match the
16276
16319
  * route definition.
16320
+ *
16321
+ * `path` can contain named groups starting with a colon (`:name`). All characters up to the
16322
+ * next slash are matched and stored in `$routeParams` under the given `name` when the route
16323
+ * matches.
16324
+ *
16277
16325
  * @param {Object} route Mapping information to be assigned to `$route.current` on route
16278
16326
  * match.
16279
16327
  *
@@ -16538,8 +16586,7 @@ function $RouteProvider(){
16538
16586
  * instance of the Controller.
16539
16587
  */
16540
16588
 
16541
- var matcher = switchRouteMatcher,
16542
- forceReload = false,
16589
+ var forceReload = false,
16543
16590
  $route = {
16544
16591
  routes: routes,
16545
16592
 
@@ -16567,21 +16614,36 @@ function $RouteProvider(){
16567
16614
 
16568
16615
  /////////////////////////////////////////////////////
16569
16616
 
16617
+ /**
16618
+ * @param on {string} current url
16619
+ * @param when {string} route when template to match the url against
16620
+ * @return {?Object}
16621
+ */
16570
16622
  function switchRouteMatcher(on, when) {
16571
16623
  // TODO(i): this code is convoluted and inefficient, we should construct the route matching
16572
16624
  // regex only once and then reuse it
16573
- var regex = '^' + when.replace(/([\.\\\(\)\^\$])/g, "\\$1") + '$',
16625
+
16626
+ // Escape regexp special characters.
16627
+ when = '^' + when.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&") + '$';
16628
+ var regex = '',
16574
16629
  params = [],
16575
16630
  dst = {};
16576
- forEach(when.split(/\W/), function(param) {
16577
- if (param) {
16578
- var paramRegExp = new RegExp(":" + param + "([\\W])");
16579
- if (regex.match(paramRegExp)) {
16580
- regex = regex.replace(paramRegExp, "([^\\/]*)$1");
16581
- params.push(param);
16582
- }
16583
- }
16584
- });
16631
+
16632
+ var re = /:(\w+)/g,
16633
+ paramMatch,
16634
+ lastMatchedIndex = 0;
16635
+
16636
+ while ((paramMatch = re.exec(when)) !== null) {
16637
+ // Find each :param in `when` and replace it with a capturing group.
16638
+ // Append all other sections of when unchanged.
16639
+ regex += when.slice(lastMatchedIndex, paramMatch.index);
16640
+ regex += '([^\\/]*)';
16641
+ params.push(paramMatch[1]);
16642
+ lastMatchedIndex = re.lastIndex;
16643
+ }
16644
+ // Append trailing path part.
16645
+ regex += when.substr(lastMatchedIndex);
16646
+
16585
16647
  var match = on.match(new RegExp(regex));
16586
16648
  if (match) {
16587
16649
  forEach(params, function(name, index) {
@@ -16670,7 +16732,7 @@ function $RouteProvider(){
16670
16732
  // Match a route
16671
16733
  var params, match;
16672
16734
  forEach(routes, function(route, path) {
16673
- if (!match && (params = matcher($location.path(), path))) {
16735
+ if (!match && (params = switchRouteMatcher($location.path(), path))) {
16674
16736
  match = inherit(route, {
16675
16737
  params: extend({}, $location.search(), params),
16676
16738
  pathParams: params});
@@ -16822,7 +16884,7 @@ function $RootScopeProvider(){
16822
16884
  expect(scope.greeting).toEqual(undefined);
16823
16885
 
16824
16886
  scope.$watch('name', function() {
16825
- this.greeting = this.salutation + ' ' + this.name + '!';
16887
+ scope.greeting = scope.salutation + ' ' + scope.name + '!';
16826
16888
  }); // initialize the watch
16827
16889
 
16828
16890
  expect(scope.greeting).toEqual(undefined);
@@ -16865,6 +16927,7 @@ function $RootScopeProvider(){
16865
16927
  this.$$nextSibling = this.$$prevSibling =
16866
16928
  this.$$childHead = this.$$childTail = null;
16867
16929
  this['this'] = this.$root = this;
16930
+ this.$$destroyed = false;
16868
16931
  this.$$asyncQueue = [];
16869
16932
  this.$$listeners = {};
16870
16933
  }
@@ -16983,7 +17046,7 @@ function $RootScopeProvider(){
16983
17046
  scope.counter = 0;
16984
17047
 
16985
17048
  expect(scope.counter).toEqual(0);
16986
- scope.$watch('name', function(newValue, oldValue) { counter = counter + 1; });
17049
+ scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });
16987
17050
  expect(scope.counter).toEqual(0);
16988
17051
 
16989
17052
  scope.$digest();
@@ -17076,7 +17139,7 @@ function $RootScopeProvider(){
17076
17139
 
17077
17140
  expect(scope.counter).toEqual(0);
17078
17141
  scope.$watch('name', function(newValue, oldValue) {
17079
- counter = counter + 1;
17142
+ scope.counter = scope.counter + 1;
17080
17143
  });
17081
17144
  expect(scope.counter).toEqual(0);
17082
17145
 
@@ -17198,10 +17261,12 @@ function $RootScopeProvider(){
17198
17261
  * perform any necessary cleanup.
17199
17262
  */
17200
17263
  $destroy: function() {
17201
- if ($rootScope == this) return; // we can't remove the root node;
17264
+ // we can't destroy the root scope or a scope that has been already destroyed
17265
+ if ($rootScope == this || this.$$destroyed) return;
17202
17266
  var parent = this.$parent;
17203
17267
 
17204
17268
  this.$broadcast('$destroy');
17269
+ this.$$destroyed = true;
17205
17270
 
17206
17271
  if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
17207
17272
  if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
@@ -17751,7 +17816,7 @@ function $HttpProvider() {
17751
17816
  /**
17752
17817
  * @ngdoc function
17753
17818
  * @name ng.$http
17754
- * @requires $httpBacked
17819
+ * @requires $httpBackend
17755
17820
  * @requires $browser
17756
17821
  * @requires $cacheFactory
17757
17822
  * @requires $rootScope
@@ -17787,8 +17852,7 @@ function $HttpProvider() {
17787
17852
  * }).
17788
17853
  * error(function(data, status, headers, config) {
17789
17854
  * // called asynchronously if an error occurs
17790
- * // or server returns response with status
17791
- * // code outside of the <200, 400) range
17855
+ * // or server returns response with an error status.
17792
17856
  * });
17793
17857
  * </pre>
17794
17858
  *
@@ -17797,6 +17861,10 @@ function $HttpProvider() {
17797
17861
  * an object representing the response. See the api signature and type info below for more
17798
17862
  * details.
17799
17863
  *
17864
+ * A response status code that falls in the [200, 300) range is considered a success status and
17865
+ * will result in the success callback being called. Note that if the response is a redirect,
17866
+ * XMLHttpRequest will transparently follow it, meaning that the error callback will not be
17867
+ * called for such responses.
17800
17868
  *
17801
17869
  * # Shortcut methods
17802
17870
  *
@@ -19634,7 +19702,6 @@ var htmlAnchorDirective = valueFn({
19634
19702
  // if we have no href url, then don't navigate anywhere.
19635
19703
  if (!element.attr('href')) {
19636
19704
  event.preventDefault();
19637
- return false; // Needed for opera
19638
19705
  }
19639
19706
  });
19640
19707
  }
@@ -19971,13 +20038,13 @@ var nullFormCtrl = {
19971
20038
  *
19972
20039
  * @property {boolean} $pristine True if user has not interacted with the form yet.
19973
20040
  * @property {boolean} $dirty True if user has already interacted with the form.
19974
- * @property {boolean} $valid True if all of the containg forms and controls are valid.
20041
+ * @property {boolean} $valid True if all of the containing forms and controls are valid.
19975
20042
  * @property {boolean} $invalid True if at least one containing control or form is invalid.
19976
20043
  *
19977
20044
  * @property {Object} $error Is an object hash, containing references to all invalid controls or
19978
20045
  * forms, where:
19979
20046
  *
19980
- * - keys are validation tokens (error names) — such as `REQUIRED`, `URL` or `EMAIL`),
20047
+ * - keys are validation tokens (error names) — such as `required`, `url` or `email`),
19981
20048
  * - values are arrays of controls or forms that are invalid with given error.
19982
20049
  *
19983
20050
  * @description
@@ -20090,7 +20157,7 @@ function FormController(element, attrs) {
20090
20157
  * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
20091
20158
  * sub-group of controls needs to be determined.
20092
20159
  *
20093
- * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into
20160
+ * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into
20094
20161
  * related scope, under this name.
20095
20162
  *
20096
20163
  */
@@ -20163,12 +20230,12 @@ function FormController(element, attrs) {
20163
20230
  </script>
20164
20231
  <form name="myForm" ng-controller="Ctrl">
20165
20232
  userType: <input name="input" ng-model="userType" required>
20166
- <span class="error" ng-show="myForm.input.$error.REQUIRED">Required!</span><br>
20233
+ <span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
20167
20234
  <tt>userType = {{userType}}</tt><br>
20168
20235
  <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>
20169
20236
  <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>
20170
20237
  <tt>myForm.$valid = {{myForm.$valid}}</tt><br>
20171
- <tt>myForm.$error.REQUIRED = {{!!myForm.$error.REQUIRED}}</tt><br>
20238
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
20172
20239
  </form>
20173
20240
  </doc:source>
20174
20241
  <doc:scenario>
@@ -22758,14 +22825,17 @@ var ngRepeatDirective = ngDirective({
22758
22825
  scope.$watch(function ngRepeatWatch(scope){
22759
22826
  var index, length,
22760
22827
  collection = scope.$eval(rhs),
22761
- collectionLength = size(collection, true),
22762
- childScope,
22828
+ cursor = iterStartElement, // current position of the node
22763
22829
  // Same as lastOrder but it has the current state. It will become the
22764
22830
  // lastOrder on the next iteration.
22765
22831
  nextOrder = new HashQueueMap(),
22832
+ arrayLength,
22833
+ childScope,
22766
22834
  key, value, // key/value of iteration
22767
- array, last, // last object information {scope, element, index}
22768
- cursor = iterStartElement; // current position of the node
22835
+ array,
22836
+ last; // last object information {scope, element, index}
22837
+
22838
+
22769
22839
 
22770
22840
  if (!isArray(collection)) {
22771
22841
  // if object, extract keys, sort them and use to determine order of iteration over obj props
@@ -22780,6 +22850,8 @@ var ngRepeatDirective = ngDirective({
22780
22850
  array = collection || [];
22781
22851
  }
22782
22852
 
22853
+ arrayLength = array.length;
22854
+
22783
22855
  // we are not using forEach for perf reasons (trying to avoid #call)
22784
22856
  for (index = 0, length = array.length; index < length; index++) {
22785
22857
  key = (collection === array) ? index : array[index];
@@ -22815,7 +22887,7 @@ var ngRepeatDirective = ngDirective({
22815
22887
  childScope.$index = index;
22816
22888
 
22817
22889
  childScope.$first = (index === 0);
22818
- childScope.$last = (index === (collectionLength - 1));
22890
+ childScope.$last = (index === (arrayLength - 1));
22819
22891
  childScope.$middle = !(childScope.$first || childScope.$last);
22820
22892
 
22821
22893
  if (!last) {
@@ -23036,52 +23108,53 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
23036
23108
  var NG_SWITCH = 'ng-switch';
23037
23109
  var ngSwitchDirective = valueFn({
23038
23110
  restrict: 'EA',
23039
- compile: function(element, attr) {
23111
+ require: 'ngSwitch',
23112
+ controller: function ngSwitchController() {
23113
+ this.cases = {};
23114
+ },
23115
+ link: function(scope, element, attr, ctrl) {
23040
23116
  var watchExpr = attr.ngSwitch || attr.on,
23041
- cases = {};
23042
-
23043
- element.data(NG_SWITCH, cases);
23044
- return function(scope, element){
23045
- var selectedTransclude,
23046
- selectedElement,
23047
- selectedScope;
23048
-
23049
- scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
23050
- if (selectedElement) {
23051
- selectedScope.$destroy();
23052
- selectedElement.remove();
23053
- selectedElement = selectedScope = null;
23054
- }
23055
- if ((selectedTransclude = cases['!' + value] || cases['?'])) {
23056
- scope.$eval(attr.change);
23057
- selectedScope = scope.$new();
23058
- selectedTransclude(selectedScope, function(caseElement) {
23059
- selectedElement = caseElement;
23060
- element.append(caseElement);
23061
- });
23062
- }
23063
- });
23064
- };
23117
+ selectedTransclude,
23118
+ selectedElement,
23119
+ selectedScope;
23120
+
23121
+ scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
23122
+ if (selectedElement) {
23123
+ selectedScope.$destroy();
23124
+ selectedElement.remove();
23125
+ selectedElement = selectedScope = null;
23126
+ }
23127
+ if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {
23128
+ scope.$eval(attr.change);
23129
+ selectedScope = scope.$new();
23130
+ selectedTransclude(selectedScope, function(caseElement) {
23131
+ selectedElement = caseElement;
23132
+ element.append(caseElement);
23133
+ });
23134
+ }
23135
+ });
23065
23136
  }
23066
23137
  });
23067
23138
 
23068
23139
  var ngSwitchWhenDirective = ngDirective({
23069
23140
  transclude: 'element',
23070
23141
  priority: 500,
23142
+ require: '^ngSwitch',
23071
23143
  compile: function(element, attrs, transclude) {
23072
- var cases = element.inheritedData(NG_SWITCH);
23073
- assertArg(cases);
23074
- cases['!' + attrs.ngSwitchWhen] = transclude;
23144
+ return function(scope, element, attr, ctrl) {
23145
+ ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;
23146
+ };
23075
23147
  }
23076
23148
  });
23077
23149
 
23078
23150
  var ngSwitchDefaultDirective = ngDirective({
23079
23151
  transclude: 'element',
23080
23152
  priority: 500,
23153
+ require: '^ngSwitch',
23081
23154
  compile: function(element, attrs, transclude) {
23082
- var cases = element.inheritedData(NG_SWITCH);
23083
- assertArg(cases);
23084
- cases['?'] = transclude;
23155
+ return function(scope, element, attr, ctrl) {
23156
+ ctrl.cases['?'] = transclude;
23157
+ };
23085
23158
  }
23086
23159
  });
23087
23160
 
@@ -23170,7 +23243,7 @@ var ngTranscludeDirective = ngDirective({
23170
23243
  <hr />
23171
23244
 
23172
23245
  <pre>$location.path() = {{$location.path()}}</pre>
23173
- <pre>$route.current.template = {{$route.current.template}}</pre>
23246
+ <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
23174
23247
  <pre>$route.current.params = {{$route.current.params}}</pre>
23175
23248
  <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
23176
23249
  <pre>$routeParams = {{$routeParams}}</pre>
@@ -23616,7 +23689,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
23616
23689
  var lastView;
23617
23690
  ctrl.$render = function() {
23618
23691
  var items = new HashMap(ctrl.$viewValue);
23619
- forEach(selectElement.children(), function(option) {
23692
+ forEach(selectElement.find('option'), function(option) {
23620
23693
  option.selected = isDefined(items.get(option.value));
23621
23694
  });
23622
23695
  };
@@ -23633,7 +23706,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
23633
23706
  selectElement.bind('change', function() {
23634
23707
  scope.$apply(function() {
23635
23708
  var array = [];
23636
- forEach(selectElement.children(), function(option) {
23709
+ forEach(selectElement.find('option'), function(option) {
23637
23710
  if (option.selected) {
23638
23711
  array.push(option.value);
23639
23712
  }
@@ -24911,160 +24984,6 @@ angular.scenario.ObjectModel.Step.prototype.setErrorStatus = function(status, er
24911
24984
  this.line = line;
24912
24985
  };
24913
24986
 
24914
- /**
24915
- * The representation of define blocks. Don't used directly, instead use
24916
- * define() in your tests.
24917
- *
24918
- * @param {string} descName Name of the block
24919
- * @param {Object} parent describe or undefined if the root.
24920
- */
24921
- angular.scenario.Describe = function(descName, parent) {
24922
- this.only = parent && parent.only;
24923
- this.beforeEachFns = [];
24924
- this.afterEachFns = [];
24925
- this.its = [];
24926
- this.children = [];
24927
- this.name = descName;
24928
- this.parent = parent;
24929
- this.id = angular.scenario.Describe.id++;
24930
-
24931
- /**
24932
- * Calls all before functions.
24933
- */
24934
- var beforeEachFns = this.beforeEachFns;
24935
- this.setupBefore = function() {
24936
- if (parent) parent.setupBefore.call(this);
24937
- angular.forEach(beforeEachFns, function(fn) { fn.call(this); }, this);
24938
- };
24939
-
24940
- /**
24941
- * Calls all after functions.
24942
- */
24943
- var afterEachFns = this.afterEachFns;
24944
- this.setupAfter = function() {
24945
- angular.forEach(afterEachFns, function(fn) { fn.call(this); }, this);
24946
- if (parent) parent.setupAfter.call(this);
24947
- };
24948
- };
24949
-
24950
- // Shared Unique ID generator for every describe block
24951
- angular.scenario.Describe.id = 0;
24952
-
24953
- // Shared Unique ID generator for every it (spec)
24954
- angular.scenario.Describe.specId = 0;
24955
-
24956
- /**
24957
- * Defines a block to execute before each it or nested describe.
24958
- *
24959
- * @param {function()} body Body of the block.
24960
- */
24961
- angular.scenario.Describe.prototype.beforeEach = function(body) {
24962
- this.beforeEachFns.push(body);
24963
- };
24964
-
24965
- /**
24966
- * Defines a block to execute after each it or nested describe.
24967
- *
24968
- * @param {function()} body Body of the block.
24969
- */
24970
- angular.scenario.Describe.prototype.afterEach = function(body) {
24971
- this.afterEachFns.push(body);
24972
- };
24973
-
24974
- /**
24975
- * Creates a new describe block that's a child of this one.
24976
- *
24977
- * @param {string} name Name of the block. Appended to the parent block's name.
24978
- * @param {function()} body Body of the block.
24979
- */
24980
- angular.scenario.Describe.prototype.describe = function(name, body) {
24981
- var child = new angular.scenario.Describe(name, this);
24982
- this.children.push(child);
24983
- body.call(child);
24984
- };
24985
-
24986
- /**
24987
- * Same as describe() but makes ddescribe blocks the only to run.
24988
- *
24989
- * @param {string} name Name of the test.
24990
- * @param {function()} body Body of the block.
24991
- */
24992
- angular.scenario.Describe.prototype.ddescribe = function(name, body) {
24993
- var child = new angular.scenario.Describe(name, this);
24994
- child.only = true;
24995
- this.children.push(child);
24996
- body.call(child);
24997
- };
24998
-
24999
- /**
25000
- * Use to disable a describe block.
25001
- */
25002
- angular.scenario.Describe.prototype.xdescribe = angular.noop;
25003
-
25004
- /**
25005
- * Defines a test.
25006
- *
25007
- * @param {string} name Name of the test.
25008
- * @param {function()} vody Body of the block.
25009
- */
25010
- angular.scenario.Describe.prototype.it = function(name, body) {
25011
- this.its.push({
25012
- id: angular.scenario.Describe.specId++,
25013
- definition: this,
25014
- only: this.only,
25015
- name: name,
25016
- before: this.setupBefore,
25017
- body: body,
25018
- after: this.setupAfter
25019
- });
25020
- };
25021
-
25022
- /**
25023
- * Same as it() but makes iit tests the only test to run.
25024
- *
25025
- * @param {string} name Name of the test.
25026
- * @param {function()} body Body of the block.
25027
- */
25028
- angular.scenario.Describe.prototype.iit = function(name, body) {
25029
- this.it.apply(this, arguments);
25030
- this.its[this.its.length-1].only = true;
25031
- };
25032
-
25033
- /**
25034
- * Use to disable a test block.
25035
- */
25036
- angular.scenario.Describe.prototype.xit = angular.noop;
25037
-
25038
- /**
25039
- * Gets an array of functions representing all the tests (recursively).
25040
- * that can be executed with SpecRunner's.
25041
- *
25042
- * @return {Array<Object>} Array of it blocks {
25043
- * definition : Object // parent Describe
25044
- * only: boolean
25045
- * name: string
25046
- * before: Function
25047
- * body: Function
25048
- * after: Function
25049
- * }
25050
- */
25051
- angular.scenario.Describe.prototype.getSpecs = function() {
25052
- var specs = arguments[0] || [];
25053
- angular.forEach(this.children, function(child) {
25054
- child.getSpecs(specs);
25055
- });
25056
- angular.forEach(this.its, function(it) {
25057
- specs.push(it);
25058
- });
25059
- var only = [];
25060
- angular.forEach(specs, function(it) {
25061
- if (it.only) {
25062
- only.push(it);
25063
- }
25064
- });
25065
- return (only.length && only) || specs;
25066
- };
25067
-
25068
24987
  /**
25069
24988
  * Runner for scenarios
25070
24989
  *
@@ -25635,13 +25554,13 @@ angular.scenario.dsl('binding', function() {
25635
25554
  */
25636
25555
  angular.scenario.dsl('input', function() {
25637
25556
  var chain = {};
25638
- var supportInputEvent = 'oninput' in document.createElement('div');
25557
+ var supportInputEvent = 'oninput' in document.createElement('div') && msie != 9;
25639
25558
 
25640
25559
  chain.enter = function(value, event) {
25641
25560
  return this.addFutureAction("input '" + this.name + "' enter '" + value + "'", function($window, $document, done) {
25642
25561
  var input = $document.elements('[ng\\:model="$1"]', this.name).filter(':input');
25643
25562
  input.val(value);
25644
- input.trigger(event || supportInputEvent && 'input' || 'change');
25563
+ input.trigger(event || (supportInputEvent ? 'input' : 'change'));
25645
25564
  done();
25646
25565
  });
25647
25566
  };