angularjs-rails 1.0.6.2 → 1.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/angularjs-rails/version.rb +1 -1
- data/vendor/assets/javascripts/angular-bootstrap-prettify.js +1 -1
- data/vendor/assets/javascripts/angular-bootstrap.js +9 -1
- data/vendor/assets/javascripts/angular-cookies.js +3 -2
- data/vendor/assets/javascripts/angular-loader.js +1 -1
- data/vendor/assets/javascripts/angular-mocks.js +33 -13
- data/vendor/assets/javascripts/angular-resource.js +1 -1
- data/vendor/assets/javascripts/angular-sanitize.js +1 -1
- data/vendor/assets/javascripts/angular-scenario.js +276 -189
- data/vendor/assets/javascripts/angular.js +276 -189
- data/vendor/assets/javascripts/unstable/angular-cookies.js +3 -2
- data/vendor/assets/javascripts/unstable/angular-loader.js +1 -1
- data/vendor/assets/javascripts/unstable/angular-mobile.js +207 -14
- data/vendor/assets/javascripts/unstable/angular-mocks.js +61 -21
- data/vendor/assets/javascripts/unstable/angular-resource.js +25 -9
- data/vendor/assets/javascripts/unstable/angular-sanitize.js +1 -1
- data/vendor/assets/javascripts/unstable/angular-scenario.js +1374 -773
- data/vendor/assets/javascripts/unstable/angular.js +1229 -667
- metadata +2 -6
- data/vendor/assets/javascripts/jstd-scenario-adapter-config.js +0 -6
- data/vendor/assets/javascripts/jstd-scenario-adapter.js +0 -185
- data/vendor/assets/javascripts/unstable/angular-bootstrap-prettify.js +0 -1838
- data/vendor/assets/javascripts/unstable/angular-bootstrap.js +0 -167
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.1.
|
2
|
+
* @license AngularJS v1.1.5
|
3
3
|
* (c) 2010-2012 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -25,19 +25,28 @@
|
|
25
25
|
* the need to interact with the low level {@link ng.$http $http} service.
|
26
26
|
*
|
27
27
|
* # Installation
|
28
|
-
* To use $resource make sure you have included the `angular-resource.js` that comes in Angular
|
29
|
-
* package. You also
|
28
|
+
* To use $resource make sure you have included the `angular-resource.js` that comes in Angular
|
29
|
+
* package. You can also find this file on Google CDN, bower as well as at
|
30
|
+
* {@link http://code.angularjs.org/ code.angularjs.org}.
|
31
|
+
*
|
30
32
|
* Finally load the module in your application:
|
31
33
|
*
|
32
34
|
* angular.module('app', ['ngResource']);
|
33
35
|
*
|
34
|
-
* and you ready to get started!
|
36
|
+
* and you are ready to get started!
|
35
37
|
*
|
36
38
|
* @param {string} url A parametrized URL template with parameters prefixed by `:` as in
|
37
39
|
* `/user/:username`. If you are using a URL with a port number (e.g.
|
38
40
|
* `http://example.com:8080/api`), you'll need to escape the colon character before the port
|
39
41
|
* number, like this: `$resource('http://example.com\\:8080/api')`.
|
40
42
|
*
|
43
|
+
* If you are using a url with a suffix, just add the suffix, like this:
|
44
|
+
* `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')
|
45
|
+
* or even `$resource('http://example.com/resource/:resource_id.:format')`
|
46
|
+
* If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be
|
47
|
+
* collapsed down to a single `.`. If you need this sequence to appear and not collapse then you
|
48
|
+
* can escape it with `/\.`.
|
49
|
+
*
|
41
50
|
* @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
|
42
51
|
* `actions` methods. If any of the parameter value is a function, it will be executed every time
|
43
52
|
* when a param value needs to be obtained for a request (unless the param was overridden).
|
@@ -82,7 +91,8 @@
|
|
82
91
|
* GET request, otherwise if a cache instance built with
|
83
92
|
* {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
|
84
93
|
* caching.
|
85
|
-
* - **`timeout`** – `{number}` – timeout in milliseconds
|
94
|
+
* - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that
|
95
|
+
* should abort the request when resolved.
|
86
96
|
* - **`withCredentials`** - `{boolean}` - whether to to set the `withCredentials` flag on the
|
87
97
|
* XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5
|
88
98
|
* requests with credentials} for more information.
|
@@ -321,7 +331,7 @@ angular.module('ngResource', ['ng']).
|
|
321
331
|
}
|
322
332
|
|
323
333
|
function Route(template, defaults) {
|
324
|
-
this.template = template
|
334
|
+
this.template = template;
|
325
335
|
this.defaults = defaults || {};
|
326
336
|
this.urlParams = {};
|
327
337
|
}
|
@@ -359,8 +369,14 @@ angular.module('ngResource', ['ng']).
|
|
359
369
|
}
|
360
370
|
});
|
361
371
|
|
362
|
-
// set the url
|
363
|
-
|
372
|
+
// strip trailing slashes and set the url
|
373
|
+
url = url.replace(/\/+$/, '');
|
374
|
+
// then replace collapse `/.` if found in the last URL path segment before the query
|
375
|
+
// E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x`
|
376
|
+
url = url.replace(/\/\.(?=\w+($|\?))/, '.');
|
377
|
+
// replace escaped `/\.` with `/.`
|
378
|
+
config.url = url.replace(/\/\\\./, '/.');
|
379
|
+
|
364
380
|
|
365
381
|
// set params - delegate param encoding to $http
|
366
382
|
forEach(params, function(value, key){
|
@@ -383,7 +399,7 @@ angular.module('ngResource', ['ng']).
|
|
383
399
|
actionParams = extend({}, paramDefaults, actionParams);
|
384
400
|
forEach(actionParams, function(value, key){
|
385
401
|
if (isFunction(value)) { value = value(); }
|
386
|
-
ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;
|
402
|
+
ids[key] = value && value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;
|
387
403
|
});
|
388
404
|
return ids;
|
389
405
|
}
|
@@ -9441,7 +9441,7 @@ if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
|
|
9441
9441
|
})( window );
|
9442
9442
|
|
9443
9443
|
/**
|
9444
|
-
* @license AngularJS v1.1.
|
9444
|
+
* @license AngularJS v1.1.5
|
9445
9445
|
* (c) 2010-2012 Google, Inc. http://angularjs.org
|
9446
9446
|
* License: MIT
|
9447
9447
|
*/
|
@@ -9529,6 +9529,27 @@ function noConflict() {
|
|
9529
9529
|
return a;
|
9530
9530
|
}
|
9531
9531
|
|
9532
|
+
/**
|
9533
|
+
* @private
|
9534
|
+
* @param {*} obj
|
9535
|
+
* @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, ...)
|
9536
|
+
*/
|
9537
|
+
function isArrayLike(obj) {
|
9538
|
+
if (!obj || (typeof obj.length !== 'number')) return false;
|
9539
|
+
|
9540
|
+
// We have on object which has length property. Should we treat it as array?
|
9541
|
+
if (typeof obj.hasOwnProperty != 'function' &&
|
9542
|
+
typeof obj.constructor != 'function') {
|
9543
|
+
// This is here for IE8: it is a bogus object treat it as array;
|
9544
|
+
return true;
|
9545
|
+
} else {
|
9546
|
+
return obj instanceof JQLite || // JQLite
|
9547
|
+
(jQuery && obj instanceof jQuery) || // jQuery
|
9548
|
+
toString.call(obj) !== '[object Object]' || // some browser native object
|
9549
|
+
typeof obj.callee === 'function'; // arguments (on IE8 looks like regular obj)
|
9550
|
+
}
|
9551
|
+
}
|
9552
|
+
|
9532
9553
|
/**
|
9533
9554
|
* @ngdoc function
|
9534
9555
|
* @name angular.forEach
|
@@ -9556,30 +9577,6 @@ function noConflict() {
|
|
9556
9577
|
* @param {Object=} context Object to become context (`this`) for the iterator function.
|
9557
9578
|
* @returns {Object|Array} Reference to `obj`.
|
9558
9579
|
*/
|
9559
|
-
|
9560
|
-
|
9561
|
-
/**
|
9562
|
-
* @private
|
9563
|
-
* @param {*} obj
|
9564
|
-
* @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, ...)
|
9565
|
-
*/
|
9566
|
-
function isArrayLike(obj) {
|
9567
|
-
if (!obj || (typeof obj.length !== 'number')) return false;
|
9568
|
-
|
9569
|
-
// We have on object which has length property. Should we treat it as array?
|
9570
|
-
if (typeof obj.hasOwnProperty != 'function' &&
|
9571
|
-
typeof obj.constructor != 'function') {
|
9572
|
-
// This is here for IE8: it is a bogus object treat it as array;
|
9573
|
-
return true;
|
9574
|
-
} else {
|
9575
|
-
return obj instanceof JQLite || // JQLite
|
9576
|
-
(jQuery && obj instanceof jQuery) || // jQuery
|
9577
|
-
toString.call(obj) !== '[object Object]' || // some browser native object
|
9578
|
-
typeof obj.callee === 'function'; // arguments (on IE8 looks like regular obj)
|
9579
|
-
}
|
9580
|
-
}
|
9581
|
-
|
9582
|
-
|
9583
9580
|
function forEach(obj, iterator, context) {
|
9584
9581
|
var key;
|
9585
9582
|
if (obj) {
|
@@ -9663,6 +9660,21 @@ function nextUid() {
|
|
9663
9660
|
return uid.join('');
|
9664
9661
|
}
|
9665
9662
|
|
9663
|
+
|
9664
|
+
/**
|
9665
|
+
* Set or clear the hashkey for an object.
|
9666
|
+
* @param obj object
|
9667
|
+
* @param h the hashkey (!truthy to delete the hashkey)
|
9668
|
+
*/
|
9669
|
+
function setHashKey(obj, h) {
|
9670
|
+
if (h) {
|
9671
|
+
obj.$$hashKey = h;
|
9672
|
+
}
|
9673
|
+
else {
|
9674
|
+
delete obj.$$hashKey;
|
9675
|
+
}
|
9676
|
+
}
|
9677
|
+
|
9666
9678
|
/**
|
9667
9679
|
* @ngdoc function
|
9668
9680
|
* @name angular.extend
|
@@ -9674,8 +9686,10 @@ function nextUid() {
|
|
9674
9686
|
*
|
9675
9687
|
* @param {Object} dst Destination object.
|
9676
9688
|
* @param {...Object} src Source object(s).
|
9689
|
+
* @returns {Object} Reference to `dst`.
|
9677
9690
|
*/
|
9678
9691
|
function extend(dst) {
|
9692
|
+
var h = dst.$$hashKey;
|
9679
9693
|
forEach(arguments, function(obj){
|
9680
9694
|
if (obj !== dst) {
|
9681
9695
|
forEach(obj, function(value, key){
|
@@ -9683,6 +9697,8 @@ function extend(dst) {
|
|
9683
9697
|
});
|
9684
9698
|
}
|
9685
9699
|
});
|
9700
|
+
|
9701
|
+
setHashKey(dst,h);
|
9686
9702
|
return dst;
|
9687
9703
|
}
|
9688
9704
|
|
@@ -10042,12 +10058,14 @@ function copy(source, destination){
|
|
10042
10058
|
destination.push(copy(source[i]));
|
10043
10059
|
}
|
10044
10060
|
} else {
|
10061
|
+
var h = destination.$$hashKey;
|
10045
10062
|
forEach(destination, function(value, key){
|
10046
10063
|
delete destination[key];
|
10047
10064
|
});
|
10048
10065
|
for ( var key in source) {
|
10049
10066
|
destination[key] = copy(source[key]);
|
10050
10067
|
}
|
10068
|
+
setHashKey(destination,h);
|
10051
10069
|
}
|
10052
10070
|
}
|
10053
10071
|
return destination;
|
@@ -10087,7 +10105,7 @@ function shallowCopy(src, dst) {
|
|
10087
10105
|
* During a property comparison, properties of `function` type and properties with names
|
10088
10106
|
* that begin with `$` are ignored.
|
10089
10107
|
*
|
10090
|
-
* Scope and DOMWindow objects are being compared only
|
10108
|
+
* Scope and DOMWindow objects are being compared only by identify (`===`).
|
10091
10109
|
*
|
10092
10110
|
* @param {*} o1 Object or value to compare.
|
10093
10111
|
* @param {*} o2 Object or value to compare.
|
@@ -10147,7 +10165,7 @@ function sliceArgs(args, startIndex) {
|
|
10147
10165
|
*
|
10148
10166
|
* @description
|
10149
10167
|
* Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
|
10150
|
-
* `fn`). You can supply optional `args` that are
|
10168
|
+
* `fn`). You can supply optional `args` that are prebound to the function. This feature is also
|
10151
10169
|
* known as [function currying](http://en.wikipedia.org/wiki/Currying).
|
10152
10170
|
*
|
10153
10171
|
* @param {Object} self Context which `fn` should be evaluated in.
|
@@ -10340,7 +10358,7 @@ function encodeUriQuery(val, pctEncodeSpaces) {
|
|
10340
10358
|
*
|
10341
10359
|
* @description
|
10342
10360
|
*
|
10343
|
-
* Use this directive to auto-bootstrap
|
10361
|
+
* Use this directive to auto-bootstrap an application. Only
|
10344
10362
|
* one directive can be used per HTML document. The directive
|
10345
10363
|
* designates the root of the application and is typically placed
|
10346
10364
|
* at the root of the page.
|
@@ -10423,12 +10441,13 @@ function bootstrap(element, modules) {
|
|
10423
10441
|
}]);
|
10424
10442
|
modules.unshift('ng');
|
10425
10443
|
var injector = createInjector(modules);
|
10426
|
-
injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
|
10427
|
-
function(scope, element, compile, injector) {
|
10444
|
+
injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animator',
|
10445
|
+
function(scope, element, compile, injector, animator) {
|
10428
10446
|
scope.$apply(function() {
|
10429
10447
|
element.data('$injector', injector);
|
10430
10448
|
compile(element)(scope);
|
10431
10449
|
});
|
10450
|
+
animator.enabled(true);
|
10432
10451
|
}]
|
10433
10452
|
);
|
10434
10453
|
return injector;
|
@@ -10479,7 +10498,7 @@ function bindJQuery() {
|
|
10479
10498
|
}
|
10480
10499
|
|
10481
10500
|
/**
|
10482
|
-
* throw error
|
10501
|
+
* throw error if the argument is falsy.
|
10483
10502
|
*/
|
10484
10503
|
function assertArg(arg, name, reason) {
|
10485
10504
|
if (!arg) {
|
@@ -10787,11 +10806,11 @@ function setupModuleLoader(window) {
|
|
10787
10806
|
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
|
10788
10807
|
*/
|
10789
10808
|
var version = {
|
10790
|
-
full: '1.1.
|
10809
|
+
full: '1.1.5', // all of these placeholder strings will be replaced by grunt's
|
10791
10810
|
major: 1, // package task
|
10792
10811
|
minor: 1,
|
10793
|
-
dot:
|
10794
|
-
codeName: '
|
10812
|
+
dot: 5,
|
10813
|
+
codeName: 'triangle-squarification'
|
10795
10814
|
};
|
10796
10815
|
|
10797
10816
|
|
@@ -10855,6 +10874,7 @@ function publishExternalAPI(angular){
|
|
10855
10874
|
ngController: ngControllerDirective,
|
10856
10875
|
ngForm: ngFormDirective,
|
10857
10876
|
ngHide: ngHideDirective,
|
10877
|
+
ngIf: ngIfDirective,
|
10858
10878
|
ngInclude: ngIncludeDirective,
|
10859
10879
|
ngInit: ngInitDirective,
|
10860
10880
|
ngNonBindable: ngNonBindableDirective,
|
@@ -10939,18 +10959,18 @@ function publishExternalAPI(angular){
|
|
10939
10959
|
* - [after()](http://api.jquery.com/after/)
|
10940
10960
|
* - [append()](http://api.jquery.com/append/)
|
10941
10961
|
* - [attr()](http://api.jquery.com/attr/)
|
10942
|
-
* - [bind()](http://api.jquery.com/bind/)
|
10943
|
-
* - [children()](http://api.jquery.com/children/)
|
10962
|
+
* - [bind()](http://api.jquery.com/bind/) - Does not support namespaces
|
10963
|
+
* - [children()](http://api.jquery.com/children/) - Does not support selectors
|
10944
10964
|
* - [clone()](http://api.jquery.com/clone/)
|
10945
10965
|
* - [contents()](http://api.jquery.com/contents/)
|
10946
10966
|
* - [css()](http://api.jquery.com/css/)
|
10947
10967
|
* - [data()](http://api.jquery.com/data/)
|
10948
10968
|
* - [eq()](http://api.jquery.com/eq/)
|
10949
|
-
* - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name
|
10969
|
+
* - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name
|
10950
10970
|
* - [hasClass()](http://api.jquery.com/hasClass/)
|
10951
10971
|
* - [html()](http://api.jquery.com/html/)
|
10952
|
-
* - [next()](http://api.jquery.com/next/)
|
10953
|
-
* - [parent()](http://api.jquery.com/parent/)
|
10972
|
+
* - [next()](http://api.jquery.com/next/) - Does not support selectors
|
10973
|
+
* - [parent()](http://api.jquery.com/parent/) - Does not support selectors
|
10954
10974
|
* - [prepend()](http://api.jquery.com/prepend/)
|
10955
10975
|
* - [prop()](http://api.jquery.com/prop/)
|
10956
10976
|
* - [ready()](http://api.jquery.com/ready/)
|
@@ -10961,8 +10981,8 @@ function publishExternalAPI(angular){
|
|
10961
10981
|
* - [replaceWith()](http://api.jquery.com/replaceWith/)
|
10962
10982
|
* - [text()](http://api.jquery.com/text/)
|
10963
10983
|
* - [toggleClass()](http://api.jquery.com/toggleClass/)
|
10964
|
-
* - [triggerHandler()](http://api.jquery.com/triggerHandler/) -
|
10965
|
-
* - [unbind()](http://api.jquery.com/unbind/)
|
10984
|
+
* - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
|
10985
|
+
* - [unbind()](http://api.jquery.com/unbind/) - Does not support namespaces
|
10966
10986
|
* - [val()](http://api.jquery.com/val/)
|
10967
10987
|
* - [wrap()](http://api.jquery.com/wrap/)
|
10968
10988
|
*
|
@@ -11467,7 +11487,7 @@ function createEventHandler(element, events) {
|
|
11467
11487
|
}
|
11468
11488
|
|
11469
11489
|
event.isDefaultPrevented = function() {
|
11470
|
-
return event.defaultPrevented;
|
11490
|
+
return event.defaultPrevented || event.returnValue == false;
|
11471
11491
|
};
|
11472
11492
|
|
11473
11493
|
forEach(events[type || event.type], function(fn) {
|
@@ -11514,23 +11534,43 @@ forEach({
|
|
11514
11534
|
|
11515
11535
|
if (!eventFns) {
|
11516
11536
|
if (type == 'mouseenter' || type == 'mouseleave') {
|
11517
|
-
var
|
11537
|
+
var contains = document.body.contains || document.body.compareDocumentPosition ?
|
11538
|
+
function( a, b ) {
|
11539
|
+
var adown = a.nodeType === 9 ? a.documentElement : a,
|
11540
|
+
bup = b && b.parentNode;
|
11541
|
+
return a === bup || !!( bup && bup.nodeType === 1 && (
|
11542
|
+
adown.contains ?
|
11543
|
+
adown.contains( bup ) :
|
11544
|
+
a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
|
11545
|
+
));
|
11546
|
+
} :
|
11547
|
+
function( a, b ) {
|
11548
|
+
if ( b ) {
|
11549
|
+
while ( (b = b.parentNode) ) {
|
11550
|
+
if ( b === a ) {
|
11551
|
+
return true;
|
11552
|
+
}
|
11553
|
+
}
|
11554
|
+
}
|
11555
|
+
return false;
|
11556
|
+
};
|
11518
11557
|
|
11519
|
-
events
|
11520
|
-
|
11558
|
+
events[type] = [];
|
11559
|
+
|
11560
|
+
// Refer to jQuery's implementation of mouseenter & mouseleave
|
11561
|
+
// Read about mouseenter and mouseleave:
|
11562
|
+
// http://www.quirksmode.org/js/events_mouse.html#link8
|
11563
|
+
var eventmap = { mouseleave : "mouseout", mouseenter : "mouseover"}
|
11564
|
+
bindFn(element, eventmap[type], function(event) {
|
11565
|
+
var ret, target = this, related = event.relatedTarget;
|
11566
|
+
// For mousenter/leave call the handler if related is outside the target.
|
11567
|
+
// NB: No relatedTarget if the mouse left/entered the browser window
|
11568
|
+
if ( !related || (related !== target && !contains(target, related)) ){
|
11569
|
+
handle(event, type);
|
11570
|
+
}
|
11521
11571
|
|
11522
|
-
bindFn(element, 'mouseover', function(event) {
|
11523
|
-
counter++;
|
11524
|
-
if (counter == 1) {
|
11525
|
-
handle(event, 'mouseenter');
|
11526
|
-
}
|
11527
|
-
});
|
11528
|
-
bindFn(element, 'mouseout', function(event) {
|
11529
|
-
counter --;
|
11530
|
-
if (counter == 0) {
|
11531
|
-
handle(event, 'mouseleave');
|
11532
|
-
}
|
11533
11572
|
});
|
11573
|
+
|
11534
11574
|
} else {
|
11535
11575
|
addEventListenerFn(element, type, handle);
|
11536
11576
|
events[type] = [];
|
@@ -11650,9 +11690,10 @@ forEach({
|
|
11650
11690
|
|
11651
11691
|
triggerHandler: function(element, eventName) {
|
11652
11692
|
var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];
|
11693
|
+
var event;
|
11653
11694
|
|
11654
11695
|
forEach(eventFns, function(fn) {
|
11655
|
-
fn.call(element,
|
11696
|
+
fn.call(element, {preventDefault: noop});
|
11656
11697
|
});
|
11657
11698
|
}
|
11658
11699
|
}, function(fn, name){
|
@@ -11803,7 +11844,7 @@ function annotate(fn) {
|
|
11803
11844
|
}
|
11804
11845
|
} else if (isArray(fn)) {
|
11805
11846
|
last = fn.length - 1;
|
11806
|
-
assertArgFn(fn[last], 'fn')
|
11847
|
+
assertArgFn(fn[last], 'fn');
|
11807
11848
|
$inject = fn.slice(0, last);
|
11808
11849
|
} else {
|
11809
11850
|
assertArgFn(fn, 'fn', true);
|
@@ -11837,7 +11878,7 @@ function annotate(fn) {
|
|
11837
11878
|
* # Injection Function Annotation
|
11838
11879
|
*
|
11839
11880
|
* JavaScript does not have annotations, and annotations are needed for dependency injection. The
|
11840
|
-
* following
|
11881
|
+
* following are all valid ways of annotating function with injection arguments and are equivalent.
|
11841
11882
|
*
|
11842
11883
|
* <pre>
|
11843
11884
|
* // inferred (only works if code not minified/obfuscated)
|
@@ -11892,6 +11933,18 @@ function annotate(fn) {
|
|
11892
11933
|
* @returns {*} the value returned by the invoked `fn` function.
|
11893
11934
|
*/
|
11894
11935
|
|
11936
|
+
/**
|
11937
|
+
* @ngdoc method
|
11938
|
+
* @name AUTO.$injector#has
|
11939
|
+
* @methodOf AUTO.$injector
|
11940
|
+
*
|
11941
|
+
* @description
|
11942
|
+
* Allows the user to query if the particular service exist.
|
11943
|
+
*
|
11944
|
+
* @param {string} Name of the service to query.
|
11945
|
+
* @returns {boolean} returns true if injector has given service.
|
11946
|
+
*/
|
11947
|
+
|
11895
11948
|
/**
|
11896
11949
|
* @ngdoc method
|
11897
11950
|
* @name AUTO.$injector#instantiate
|
@@ -11966,7 +12019,7 @@ function annotate(fn) {
|
|
11966
12019
|
* // ...
|
11967
12020
|
* };
|
11968
12021
|
* tmpFn.$inject = ['$compile', '$rootScope'];
|
11969
|
-
* injector.invoke(
|
12022
|
+
* injector.invoke(tmpFn);
|
11970
12023
|
*
|
11971
12024
|
* // To better support inline function the inline annotation is supported
|
11972
12025
|
* injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
|
@@ -12019,7 +12072,7 @@ function annotate(fn) {
|
|
12019
12072
|
*
|
12020
12073
|
* beforeEach(module(function($provide) {
|
12021
12074
|
* $provide.provider('greet', GreetProvider);
|
12022
|
-
* });
|
12075
|
+
* }));
|
12023
12076
|
*
|
12024
12077
|
* it('should greet', inject(function(greet) {
|
12025
12078
|
* expect(greet('angular')).toEqual('Hello angular!');
|
@@ -12032,9 +12085,7 @@ function annotate(fn) {
|
|
12032
12085
|
* inject(function(greet) {
|
12033
12086
|
* expect(greet('angular')).toEqual('Ahoj angular!');
|
12034
12087
|
* });
|
12035
|
-
* )
|
12036
|
-
*
|
12037
|
-
* });
|
12088
|
+
* });
|
12038
12089
|
* </pre>
|
12039
12090
|
*/
|
12040
12091
|
|
@@ -12128,7 +12179,7 @@ function annotate(fn) {
|
|
12128
12179
|
*
|
12129
12180
|
* @param {string} name The name of the service to decorate.
|
12130
12181
|
* @param {function()} decorator This function will be invoked when the service needs to be
|
12131
|
-
*
|
12182
|
+
* instantiated. The function is called using the {@link AUTO.$injector#invoke
|
12132
12183
|
* injector.invoke} method and is therefore fully injectable. Local injection arguments:
|
12133
12184
|
*
|
12134
12185
|
* * `$delegate` - The original service instance, which can be monkey patched, configured,
|
@@ -12327,6 +12378,8 @@ function createInjector(modulesToLoad) {
|
|
12327
12378
|
var Constructor = function() {},
|
12328
12379
|
instance, returnedValue;
|
12329
12380
|
|
12381
|
+
// Check if Type is annotated and use just the given function at n-1 as parameter
|
12382
|
+
// e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
|
12330
12383
|
Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;
|
12331
12384
|
instance = new Constructor();
|
12332
12385
|
returnedValue = invoke(Type, instance, locals);
|
@@ -12338,7 +12391,10 @@ function createInjector(modulesToLoad) {
|
|
12338
12391
|
invoke: invoke,
|
12339
12392
|
instantiate: instantiate,
|
12340
12393
|
get: getService,
|
12341
|
-
annotate: annotate
|
12394
|
+
annotate: annotate,
|
12395
|
+
has: function(name) {
|
12396
|
+
return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
|
12397
|
+
}
|
12342
12398
|
};
|
12343
12399
|
}
|
12344
12400
|
}
|
@@ -12464,18 +12520,14 @@ function $AnimationProvider($provide) {
|
|
12464
12520
|
*/
|
12465
12521
|
return function $animation(name) {
|
12466
12522
|
if (name) {
|
12467
|
-
|
12468
|
-
|
12469
|
-
|
12470
|
-
//TODO(misko): this is a hack! we should have a better way to test if the injector has a given key.
|
12471
|
-
// The issue is that the animations are optional, and if not present they should be silently ignored.
|
12472
|
-
// The proper way to fix this is to add API onto the injector so that we can ask to see if a given
|
12473
|
-
// animation is supported.
|
12523
|
+
var animationName = camelCase(name) + suffix;
|
12524
|
+
if ($injector.has(animationName)) {
|
12525
|
+
return $injector.get(animationName);
|
12474
12526
|
}
|
12475
12527
|
}
|
12476
|
-
}
|
12528
|
+
};
|
12477
12529
|
}];
|
12478
|
-
}
|
12530
|
+
}
|
12479
12531
|
|
12480
12532
|
// NOTE: this is a pseudo directive.
|
12481
12533
|
|
@@ -12485,18 +12537,21 @@ function $AnimationProvider($provide) {
|
|
12485
12537
|
*
|
12486
12538
|
* @description
|
12487
12539
|
* The `ngAnimate` directive works as an attribute that is attached alongside pre-existing directives.
|
12488
|
-
* It effects how the directive will perform DOM manipulation. This allows for complex animations to take place
|
12489
|
-
* without
|
12540
|
+
* It effects how the directive will perform DOM manipulation. This allows for complex animations to take place
|
12541
|
+
* without burdening the directive which uses the animation with animation details. The built in directives
|
12490
12542
|
* `ngRepeat`, `ngInclude`, `ngSwitch`, `ngShow`, `ngHide` and `ngView` already accept `ngAnimate` directive.
|
12491
12543
|
* Custom directives can take advantage of animation through {@link ng.$animator $animator service}.
|
12492
12544
|
*
|
12493
12545
|
* Below is a more detailed breakdown of the supported callback events provided by pre-exisitng ng directives:
|
12494
12546
|
*
|
12495
|
-
*
|
12496
|
-
*
|
12497
|
-
*
|
12498
|
-
*
|
12499
|
-
*
|
12547
|
+
* | Directive | Supported Animations |
|
12548
|
+
* |========================================================== |====================================================|
|
12549
|
+
* | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move |
|
12550
|
+
* | {@link ng.directive:ngView#animations ngView} | enter and leave |
|
12551
|
+
* | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave |
|
12552
|
+
* | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave |
|
12553
|
+
* | {@link ng.directive:ngIf#animations ngIf} | enter and leave |
|
12554
|
+
* | {@link ng.directive:ngShow#animations ngShow & ngHide} | show and hide |
|
12500
12555
|
*
|
12501
12556
|
* You can find out more information about animations upon visiting each directive page.
|
12502
12557
|
*
|
@@ -12517,23 +12572,26 @@ function $AnimationProvider($provide) {
|
|
12517
12572
|
*
|
12518
12573
|
* The `event1` and `event2` attributes refer to the animation events specific to the directive that has been assigned.
|
12519
12574
|
*
|
12575
|
+
* Keep in mind that if an animation is running, no child element of such animation can also be animated.
|
12576
|
+
*
|
12520
12577
|
* <h2>CSS-defined Animations</h2>
|
12521
|
-
* By default, ngAnimate attaches two
|
12522
|
-
*
|
12523
|
-
*
|
12578
|
+
* By default, ngAnimate attaches two CSS classes per animation event to the DOM element to achieve the animation.
|
12579
|
+
* It is up to you, the developer, to ensure that the animations take place using cross-browser CSS3 transitions as
|
12580
|
+
* well as CSS animations.
|
12581
|
+
*
|
12582
|
+
* The following code below demonstrates how to perform animations using **CSS transitions** with ngAnimate:
|
12524
12583
|
*
|
12525
12584
|
* <pre>
|
12526
12585
|
* <style type="text/css">
|
12527
12586
|
* /*
|
12528
|
-
* The animate-enter
|
12587
|
+
* The animate-enter CSS class is the event name that you
|
12529
12588
|
* have provided within the ngAnimate attribute.
|
12530
12589
|
* */
|
12531
|
-
* .animate-enter
|
12590
|
+
* .animate-enter {
|
12532
12591
|
* -webkit-transition: 1s linear all; /* Safari/Chrome */
|
12533
12592
|
* -moz-transition: 1s linear all; /* Firefox */
|
12534
|
-
* -ms-transition: 1s linear all; /* IE10 */
|
12535
12593
|
* -o-transition: 1s linear all; /* Opera */
|
12536
|
-
* transition: 1s linear all; /* Future Browsers */
|
12594
|
+
* transition: 1s linear all; /* IE10+ and Future Browsers */
|
12537
12595
|
*
|
12538
12596
|
* /* The animation preparation code */
|
12539
12597
|
* opacity: 0;
|
@@ -12544,7 +12602,7 @@ function $AnimationProvider($provide) {
|
|
12544
12602
|
* classes together to avoid any CSS-specificity
|
12545
12603
|
* conflicts
|
12546
12604
|
* */
|
12547
|
-
* .animate-enter
|
12605
|
+
* .animate-enter.animate-enter-active {
|
12548
12606
|
* /* The animation code itself */
|
12549
12607
|
* opacity: 1;
|
12550
12608
|
* }
|
@@ -12553,16 +12611,49 @@ function $AnimationProvider($provide) {
|
|
12553
12611
|
* <div ng-directive ng-animate="{enter: 'animate-enter'}"></div>
|
12554
12612
|
* </pre>
|
12555
12613
|
*
|
12556
|
-
*
|
12557
|
-
*
|
12614
|
+
* The following code below demonstrates how to perform animations using **CSS animations** with ngAnimate:
|
12615
|
+
*
|
12616
|
+
* <pre>
|
12617
|
+
* <style type="text/css">
|
12618
|
+
* .animate-enter {
|
12619
|
+
* -webkit-animation: enter_sequence 1s linear; /* Safari/Chrome */
|
12620
|
+
* -moz-animation: enter_sequence 1s linear; /* Firefox */
|
12621
|
+
* -o-animation: enter_sequence 1s linear; /* Opera */
|
12622
|
+
* animation: enter_sequence 1s linear; /* IE10+ and Future Browsers */
|
12623
|
+
* }
|
12624
|
+
* @-webkit-keyframes enter_sequence {
|
12625
|
+
* from { opacity:0; }
|
12626
|
+
* to { opacity:1; }
|
12627
|
+
* }
|
12628
|
+
* @-moz-keyframes enter_sequence {
|
12629
|
+
* from { opacity:0; }
|
12630
|
+
* to { opacity:1; }
|
12631
|
+
* }
|
12632
|
+
* @-o-keyframes enter_sequence {
|
12633
|
+
* from { opacity:0; }
|
12634
|
+
* to { opacity:1; }
|
12635
|
+
* }
|
12636
|
+
* @keyframes enter_sequence {
|
12637
|
+
* from { opacity:0; }
|
12638
|
+
* to { opacity:1; }
|
12639
|
+
* }
|
12640
|
+
* </style>
|
12641
|
+
*
|
12642
|
+
* <div ng-directive ng-animate="{enter: 'animate-enter'}"></div>
|
12643
|
+
* </pre>
|
12644
|
+
*
|
12645
|
+
* ngAnimate will first examine any CSS animation code and then fallback to using CSS transitions.
|
12646
|
+
*
|
12647
|
+
* Upon DOM mutation, the event class is added first, then the browser is allowed to reflow the content and then,
|
12648
|
+
* the active class is added to trigger the animation. The ngAnimate directive will automatically extract the duration
|
12558
12649
|
* of the animation to determine when the animation ends. Once the animation is over then both CSS classes will be
|
12559
|
-
* removed from the DOM. If a browser does not support CSS transitions then the animation will start and end
|
12650
|
+
* removed from the DOM. If a browser does not support CSS transitions or CSS animations then the animation will start and end
|
12560
12651
|
* immediately resulting in a DOM element that is at it's final state. This final state is when the DOM element
|
12561
|
-
* has no CSS animation classes surrounding it.
|
12652
|
+
* has no CSS transition/animation classes surrounding it.
|
12562
12653
|
*
|
12563
12654
|
* <h2>JavaScript-defined Animations</h2>
|
12564
|
-
* In the event that you do not want to use CSS3 animations or if you wish to offer animations to browsers that do not
|
12565
|
-
* yet support them, then you can make use of JavaScript animations defined inside
|
12655
|
+
* In the event that you do not want to use CSS3 transitions or CSS3 animations or if you wish to offer animations to browsers that do not
|
12656
|
+
* yet support them, then you can make use of JavaScript animations defined inside of your AngularJS module.
|
12566
12657
|
*
|
12567
12658
|
* <pre>
|
12568
12659
|
* var ngModule = angular.module('YourApp', []);
|
@@ -12589,8 +12680,8 @@ function $AnimationProvider($provide) {
|
|
12589
12680
|
*
|
12590
12681
|
* As you can see, the JavaScript code follows a similar template to the CSS3 animations. Once defined, the animation
|
12591
12682
|
* can be used in the same way with the ngAnimate attribute. Keep in mind that, when using JavaScript-enabled
|
12592
|
-
* animations, ngAnimate will also add in the same CSS classes that CSS-enabled animations do (even if you're using
|
12593
|
-
*
|
12683
|
+
* animations, ngAnimate will also add in the same CSS classes that CSS-enabled animations do (even if you're not using
|
12684
|
+
* CSS animations) to animated the element, but it will not attempt to find any CSS3 transition or animation duration/delay values.
|
12594
12685
|
* It will instead close off the animation once the provided done function is executed. So it's important that you
|
12595
12686
|
* make sure your animations remember to fire off the done function once the animations are complete.
|
12596
12687
|
*
|
@@ -12598,151 +12689,214 @@ function $AnimationProvider($provide) {
|
|
12598
12689
|
*
|
12599
12690
|
*/
|
12600
12691
|
|
12601
|
-
/**
|
12602
|
-
* @ngdoc function
|
12603
|
-
* @name ng.$animator
|
12604
|
-
*
|
12605
|
-
* @description
|
12606
|
-
* The $animator service provides the DOM manipulation API which is decorated with animations.
|
12607
|
-
*
|
12608
|
-
* @param {Scope} scope the scope for the ng-animate.
|
12609
|
-
* @param {Attributes} attr the attributes object which contains the ngAnimate key / value pair. (The attributes are
|
12610
|
-
* passed into the linking function of the directive using the `$animator`.)
|
12611
|
-
* @return {object} the animator object which contains the enter, leave, move, show, hide and animate methods.
|
12612
|
-
*/
|
12613
12692
|
var $AnimatorProvider = function() {
|
12614
|
-
|
12615
|
-
|
12616
|
-
var ngAnimateAttr = attrs.ngAnimate;
|
12617
|
-
var animator = {};
|
12618
|
-
|
12619
|
-
/**
|
12620
|
-
* @ngdoc function
|
12621
|
-
* @name ng.animator#enter
|
12622
|
-
* @methodOf ng.$animator
|
12623
|
-
* @function
|
12624
|
-
*
|
12625
|
-
* @description
|
12626
|
-
* Injects the element object into the DOM (inside of the parent element) and then runs the enter animation.
|
12627
|
-
*
|
12628
|
-
* @param {jQuery/jqLite element} element the element that will be the focus of the enter animation
|
12629
|
-
* @param {jQuery/jqLite element} parent the parent element of the element that will be the focus of the enter animation
|
12630
|
-
* @param {jQuery/jqLite element} after the sibling element (which is the previous element) of the element that will be the focus of the enter animation
|
12631
|
-
*/
|
12632
|
-
animator.enter = animateActionFactory('enter', insert, noop);
|
12693
|
+
var NG_ANIMATE_CONTROLLER = '$ngAnimateController';
|
12694
|
+
var rootAnimateController = {running:true};
|
12633
12695
|
|
12634
|
-
|
12635
|
-
|
12636
|
-
|
12637
|
-
* @methodOf ng.$animator
|
12638
|
-
* @function
|
12639
|
-
*
|
12640
|
-
* @description
|
12641
|
-
* Runs the leave animation operation and, upon completion, removes the element from the DOM.
|
12642
|
-
*
|
12643
|
-
* @param {jQuery/jqLite element} element the element that will be the focus of the leave animation
|
12644
|
-
* @param {jQuery/jqLite element} parent the parent element of the element that will be the focus of the leave animation
|
12645
|
-
*/
|
12646
|
-
animator.leave = animateActionFactory('leave', noop, remove);
|
12696
|
+
this.$get = ['$animation', '$window', '$sniffer', '$rootElement', '$rootScope',
|
12697
|
+
function($animation, $window, $sniffer, $rootElement, $rootScope) {
|
12698
|
+
$rootElement.data(NG_ANIMATE_CONTROLLER, rootAnimateController);
|
12647
12699
|
|
12648
|
-
|
12649
|
-
|
12650
|
-
|
12651
|
-
|
12652
|
-
|
12653
|
-
|
12654
|
-
|
12655
|
-
|
12656
|
-
|
12657
|
-
|
12658
|
-
|
12659
|
-
|
12660
|
-
|
12661
|
-
|
12662
|
-
|
12663
|
-
|
12664
|
-
|
12665
|
-
|
12666
|
-
|
12667
|
-
|
12668
|
-
|
12669
|
-
|
12670
|
-
|
12671
|
-
|
12672
|
-
|
12673
|
-
|
12674
|
-
|
12675
|
-
|
12676
|
-
|
12677
|
-
|
12678
|
-
|
12679
|
-
|
12680
|
-
|
12681
|
-
|
12682
|
-
|
12683
|
-
|
12684
|
-
|
12685
|
-
|
12686
|
-
|
12687
|
-
|
12688
|
-
|
12700
|
+
/**
|
12701
|
+
* @ngdoc function
|
12702
|
+
* @name ng.$animator
|
12703
|
+
* @function
|
12704
|
+
*
|
12705
|
+
* @description
|
12706
|
+
* The $animator.create service provides the DOM manipulation API which is decorated with animations.
|
12707
|
+
*
|
12708
|
+
* @param {Scope} scope the scope for the ng-animate.
|
12709
|
+
* @param {Attributes} attr the attributes object which contains the ngAnimate key / value pair. (The attributes are
|
12710
|
+
* passed into the linking function of the directive using the `$animator`.)
|
12711
|
+
* @return {object} the animator object which contains the enter, leave, move, show, hide and animate methods.
|
12712
|
+
*/
|
12713
|
+
var AnimatorService = function(scope, attrs) {
|
12714
|
+
var animator = {};
|
12715
|
+
|
12716
|
+
/**
|
12717
|
+
* @ngdoc function
|
12718
|
+
* @name ng.animator#enter
|
12719
|
+
* @methodOf ng.$animator
|
12720
|
+
* @function
|
12721
|
+
*
|
12722
|
+
* @description
|
12723
|
+
* Injects the element object into the DOM (inside of the parent element) and then runs the enter animation.
|
12724
|
+
*
|
12725
|
+
* @param {jQuery/jqLite element} element the element that will be the focus of the enter animation
|
12726
|
+
* @param {jQuery/jqLite element} parent the parent element of the element that will be the focus of the enter animation
|
12727
|
+
* @param {jQuery/jqLite element} after the sibling element (which is the previous element) of the element that will be the focus of the enter animation
|
12728
|
+
*/
|
12729
|
+
animator.enter = animateActionFactory('enter', insert, noop);
|
12730
|
+
|
12731
|
+
/**
|
12732
|
+
* @ngdoc function
|
12733
|
+
* @name ng.animator#leave
|
12734
|
+
* @methodOf ng.$animator
|
12735
|
+
* @function
|
12736
|
+
*
|
12737
|
+
* @description
|
12738
|
+
* Runs the leave animation operation and, upon completion, removes the element from the DOM.
|
12739
|
+
*
|
12740
|
+
* @param {jQuery/jqLite element} element the element that will be the focus of the leave animation
|
12741
|
+
* @param {jQuery/jqLite element} parent the parent element of the element that will be the focus of the leave animation
|
12742
|
+
*/
|
12743
|
+
animator.leave = animateActionFactory('leave', noop, remove);
|
12744
|
+
|
12745
|
+
/**
|
12746
|
+
* @ngdoc function
|
12747
|
+
* @name ng.animator#move
|
12748
|
+
* @methodOf ng.$animator
|
12749
|
+
* @function
|
12750
|
+
*
|
12751
|
+
* @description
|
12752
|
+
* Fires the move DOM operation. Just before the animation starts, the animator will either append it into the parent container or
|
12753
|
+
* add the element directly after the after element if present. Then the move animation will be run.
|
12754
|
+
*
|
12755
|
+
* @param {jQuery/jqLite element} element the element that will be the focus of the move animation
|
12756
|
+
* @param {jQuery/jqLite element} parent the parent element of the element that will be the focus of the move animation
|
12757
|
+
* @param {jQuery/jqLite element} after the sibling element (which is the previous element) of the element that will be the focus of the move animation
|
12758
|
+
*/
|
12759
|
+
animator.move = animateActionFactory('move', move, noop);
|
12760
|
+
|
12761
|
+
/**
|
12762
|
+
* @ngdoc function
|
12763
|
+
* @name ng.animator#show
|
12764
|
+
* @methodOf ng.$animator
|
12765
|
+
* @function
|
12766
|
+
*
|
12767
|
+
* @description
|
12768
|
+
* Reveals the element by setting the CSS property `display` to `block` and then starts the show animation directly after.
|
12769
|
+
*
|
12770
|
+
* @param {jQuery/jqLite element} element the element that will be rendered visible or hidden
|
12771
|
+
*/
|
12772
|
+
animator.show = animateActionFactory('show', show, noop);
|
12773
|
+
|
12774
|
+
/**
|
12775
|
+
* @ngdoc function
|
12776
|
+
* @name ng.animator#hide
|
12777
|
+
* @methodOf ng.$animator
|
12778
|
+
*
|
12779
|
+
* @description
|
12780
|
+
* Starts the hide animation first and sets the CSS `display` property to `none` upon completion.
|
12781
|
+
*
|
12782
|
+
* @param {jQuery/jqLite element} element the element that will be rendered visible or hidden
|
12783
|
+
*/
|
12784
|
+
animator.hide = animateActionFactory('hide', noop, hide);
|
12689
12785
|
|
12690
|
-
|
12691
|
-
|
12692
|
-
|
12693
|
-
|
12694
|
-
|
12695
|
-
|
12786
|
+
/**
|
12787
|
+
* @ngdoc function
|
12788
|
+
* @name ng.animator#animate
|
12789
|
+
* @methodOf ng.$animator
|
12790
|
+
*
|
12791
|
+
* @description
|
12792
|
+
* Triggers a custom animation event to be executed on the given element
|
12793
|
+
*
|
12794
|
+
* @param {jQuery/jqLite element} element that will be animated
|
12795
|
+
*/
|
12796
|
+
animator.animate = function(event, element) {
|
12797
|
+
animateActionFactory(event, noop, noop)(element);
|
12798
|
+
}
|
12799
|
+
return animator;
|
12800
|
+
|
12801
|
+
function animateActionFactory(type, beforeFn, afterFn) {
|
12802
|
+
return function(element, parent, after) {
|
12803
|
+
var ngAnimateValue = scope.$eval(attrs.ngAnimate);
|
12804
|
+
var className = ngAnimateValue
|
12805
|
+
? isObject(ngAnimateValue) ? ngAnimateValue[type] : ngAnimateValue + '-' + type
|
12806
|
+
: '';
|
12807
|
+
var animationPolyfill = $animation(className);
|
12808
|
+
var polyfillSetup = animationPolyfill && animationPolyfill.setup;
|
12809
|
+
var polyfillStart = animationPolyfill && animationPolyfill.start;
|
12810
|
+
var polyfillCancel = animationPolyfill && animationPolyfill.cancel;
|
12811
|
+
|
12812
|
+
if (!className) {
|
12813
|
+
beforeFn(element, parent, after);
|
12814
|
+
afterFn(element, parent, after);
|
12815
|
+
} else {
|
12816
|
+
var activeClassName = className + '-active';
|
12696
12817
|
|
12697
|
-
|
12698
|
-
|
12818
|
+
if (!parent) {
|
12819
|
+
parent = after ? after.parent() : element.parent();
|
12820
|
+
}
|
12821
|
+
if ((!$sniffer.transitions && !polyfillSetup && !polyfillStart) ||
|
12822
|
+
(parent.inheritedData(NG_ANIMATE_CONTROLLER) || noop).running) {
|
12823
|
+
beforeFn(element, parent, after);
|
12824
|
+
afterFn(element, parent, after);
|
12825
|
+
return;
|
12826
|
+
}
|
12699
12827
|
|
12700
|
-
|
12701
|
-
|
12702
|
-
|
12703
|
-
|
12704
|
-
|
12705
|
-
} else {
|
12706
|
-
var setupClass = className + '-setup';
|
12707
|
-
var startClass = className + '-start';
|
12828
|
+
var animationData = element.data(NG_ANIMATE_CONTROLLER) || {};
|
12829
|
+
if(animationData.running) {
|
12830
|
+
(polyfillCancel || noop)(element);
|
12831
|
+
animationData.done();
|
12832
|
+
}
|
12708
12833
|
|
12709
|
-
|
12710
|
-
|
12834
|
+
element.data(NG_ANIMATE_CONTROLLER, {running:true, done:done});
|
12835
|
+
element.addClass(className);
|
12711
12836
|
beforeFn(element, parent, after);
|
12712
|
-
|
12713
|
-
return;
|
12714
|
-
}
|
12837
|
+
if (element.length == 0) return done();
|
12715
12838
|
|
12716
|
-
|
12717
|
-
beforeFn(element, parent, after);
|
12718
|
-
if (element.length == 0) return done();
|
12839
|
+
var memento = (polyfillSetup || noop)(element);
|
12719
12840
|
|
12720
|
-
|
12841
|
+
// $window.setTimeout(beginAnimation, 0); this was causing the element not to animate
|
12842
|
+
// keep at 1 for animation dom rerender
|
12843
|
+
$window.setTimeout(beginAnimation, 1);
|
12844
|
+
}
|
12721
12845
|
|
12722
|
-
|
12723
|
-
|
12724
|
-
|
12846
|
+
function parseMaxTime(str) {
|
12847
|
+
var total = 0, values = isString(str) ? str.split(/\s*,\s*/) : [];
|
12848
|
+
forEach(values, function(value) {
|
12849
|
+
total = Math.max(parseFloat(value) || 0, total);
|
12850
|
+
});
|
12851
|
+
return total;
|
12852
|
+
}
|
12725
12853
|
|
12726
12854
|
function beginAnimation() {
|
12727
|
-
element.addClass(
|
12855
|
+
element.addClass(activeClassName);
|
12728
12856
|
if (polyfillStart) {
|
12729
12857
|
polyfillStart(element, done, memento);
|
12730
12858
|
} else if (isFunction($window.getComputedStyle)) {
|
12859
|
+
//one day all browsers will have these properties
|
12860
|
+
var w3cAnimationProp = 'animation';
|
12861
|
+
var w3cTransitionProp = 'transition';
|
12862
|
+
|
12863
|
+
//but some still use vendor-prefixed styles
|
12864
|
+
var vendorAnimationProp = $sniffer.vendorPrefix + 'Animation';
|
12731
12865
|
var vendorTransitionProp = $sniffer.vendorPrefix + 'Transition';
|
12732
|
-
var w3cTransitionProp = 'transition'; //one day all browsers will have this
|
12733
12866
|
|
12734
|
-
var durationKey = 'Duration'
|
12735
|
-
|
12867
|
+
var durationKey = 'Duration',
|
12868
|
+
delayKey = 'Delay',
|
12869
|
+
animationIterationCountKey = 'IterationCount',
|
12870
|
+
duration = 0;
|
12871
|
+
|
12736
12872
|
//we want all the styles defined before and after
|
12873
|
+
var ELEMENT_NODE = 1;
|
12737
12874
|
forEach(element, function(element) {
|
12738
|
-
|
12739
|
-
|
12740
|
-
|
12741
|
-
|
12742
|
-
|
12743
|
-
|
12744
|
-
|
12875
|
+
if (element.nodeType == ELEMENT_NODE) {
|
12876
|
+
var w3cProp = w3cTransitionProp,
|
12877
|
+
vendorProp = vendorTransitionProp,
|
12878
|
+
iterations = 1,
|
12879
|
+
elementStyles = $window.getComputedStyle(element) || {};
|
12880
|
+
|
12881
|
+
//use CSS Animations over CSS Transitions
|
12882
|
+
if(parseFloat(elementStyles[w3cAnimationProp + durationKey]) > 0 ||
|
12883
|
+
parseFloat(elementStyles[vendorAnimationProp + durationKey]) > 0) {
|
12884
|
+
w3cProp = w3cAnimationProp;
|
12885
|
+
vendorProp = vendorAnimationProp;
|
12886
|
+
iterations = Math.max(parseInt(elementStyles[w3cProp + animationIterationCountKey]) || 0,
|
12887
|
+
parseInt(elementStyles[vendorProp + animationIterationCountKey]) || 0,
|
12888
|
+
iterations);
|
12889
|
+
}
|
12890
|
+
|
12891
|
+
var parsedDelay = Math.max(parseMaxTime(elementStyles[w3cProp + delayKey]),
|
12892
|
+
parseMaxTime(elementStyles[vendorProp + delayKey]));
|
12745
12893
|
|
12894
|
+
var parsedDuration = Math.max(parseMaxTime(elementStyles[w3cProp + durationKey]),
|
12895
|
+
parseMaxTime(elementStyles[vendorProp + durationKey]));
|
12896
|
+
|
12897
|
+
duration = Math.max(parsedDelay + (iterations * parsedDuration), duration);
|
12898
|
+
}
|
12899
|
+
});
|
12746
12900
|
$window.setTimeout(done, duration * 1000);
|
12747
12901
|
} else {
|
12748
12902
|
done();
|
@@ -12750,40 +12904,65 @@ var $AnimatorProvider = function() {
|
|
12750
12904
|
}
|
12751
12905
|
|
12752
12906
|
function done() {
|
12753
|
-
|
12754
|
-
|
12755
|
-
|
12907
|
+
if(!done.run) {
|
12908
|
+
done.run = true;
|
12909
|
+
afterFn(element, parent, after);
|
12910
|
+
element.removeClass(className);
|
12911
|
+
element.removeClass(activeClassName);
|
12912
|
+
element.removeData(NG_ANIMATE_CONTROLLER);
|
12913
|
+
}
|
12756
12914
|
}
|
12915
|
+
};
|
12916
|
+
}
|
12917
|
+
|
12918
|
+
function show(element) {
|
12919
|
+
element.css('display', '');
|
12920
|
+
}
|
12921
|
+
|
12922
|
+
function hide(element) {
|
12923
|
+
element.css('display', 'none');
|
12924
|
+
}
|
12925
|
+
|
12926
|
+
function insert(element, parent, after) {
|
12927
|
+
if (after) {
|
12928
|
+
after.after(element);
|
12929
|
+
} else {
|
12930
|
+
parent.append(element);
|
12757
12931
|
}
|
12758
12932
|
}
|
12759
|
-
|
12760
|
-
|
12761
|
-
|
12762
|
-
|
12763
|
-
|
12764
|
-
|
12765
|
-
|
12766
|
-
|
12767
|
-
|
12768
|
-
|
12933
|
+
|
12934
|
+
function remove(element) {
|
12935
|
+
element.remove();
|
12936
|
+
}
|
12937
|
+
|
12938
|
+
function move(element, parent, after) {
|
12939
|
+
// Do not remove element before insert. Removing will cause data associated with the
|
12940
|
+
// element to be dropped. Insert will implicitly do the remove.
|
12941
|
+
insert(element, parent, after);
|
12942
|
+
}
|
12943
|
+
};
|
12769
12944
|
|
12770
|
-
|
12771
|
-
|
12772
|
-
|
12773
|
-
|
12774
|
-
|
12945
|
+
/**
|
12946
|
+
* @ngdoc function
|
12947
|
+
* @name ng.animator#enabled
|
12948
|
+
* @methodOf ng.$animator
|
12949
|
+
* @function
|
12950
|
+
*
|
12951
|
+
* @param {Boolean=} If provided then set the animation on or off.
|
12952
|
+
* @return {Boolean} Current animation state.
|
12953
|
+
*
|
12954
|
+
* @description
|
12955
|
+
* Globally enables/disables animations.
|
12956
|
+
*
|
12957
|
+
*/
|
12958
|
+
AnimatorService.enabled = function(value) {
|
12959
|
+
if (arguments.length) {
|
12960
|
+
rootAnimateController.running = !value;
|
12775
12961
|
}
|
12776
|
-
|
12777
|
-
|
12778
|
-
function remove(element) {
|
12779
|
-
element.remove();
|
12780
|
-
}
|
12962
|
+
return !rootAnimateController.running;
|
12963
|
+
};
|
12781
12964
|
|
12782
|
-
|
12783
|
-
// Do not remove element before insert. Removing will cause data associated with the
|
12784
|
-
// element to be dropped. Insert will implicitly do the remove.
|
12785
|
-
insert(element, parent, after);
|
12786
|
-
}
|
12965
|
+
return AnimatorService;
|
12787
12966
|
}];
|
12788
12967
|
};
|
12789
12968
|
|
@@ -13084,7 +13263,13 @@ function Browser(window, document, $log, $sniffer) {
|
|
13084
13263
|
cookie = cookieArray[i];
|
13085
13264
|
index = cookie.indexOf('=');
|
13086
13265
|
if (index > 0) { //ignore nameless cookies
|
13087
|
-
|
13266
|
+
var name = unescape(cookie.substring(0, index));
|
13267
|
+
// the first value that is seen for a cookie is the most
|
13268
|
+
// specific one. values for the same cookie name that
|
13269
|
+
// follow are for less specific paths.
|
13270
|
+
if (lastCookies[name] === undefined) {
|
13271
|
+
lastCookies[name] = unescape(cookie.substring(index + 1));
|
13272
|
+
}
|
13088
13273
|
}
|
13089
13274
|
}
|
13090
13275
|
}
|
@@ -13897,9 +14082,9 @@ function $CompileProvider($provide) {
|
|
13897
14082
|
|
13898
14083
|
|
13899
14084
|
/**
|
13900
|
-
* Once the directives have been collected their compile functions
|
14085
|
+
* Once the directives have been collected, their compile functions are executed. This method
|
13901
14086
|
* is responsible for inlining directive templates as well as terminating the application
|
13902
|
-
* of the directives if the terminal directive has been reached
|
14087
|
+
* of the directives if the terminal directive has been reached.
|
13903
14088
|
*
|
13904
14089
|
* @param {Array} directives Array of collected directives to execute their compile function.
|
13905
14090
|
* this needs to be pre-sorted by priority order.
|
@@ -13907,11 +14092,11 @@ function $CompileProvider($provide) {
|
|
13907
14092
|
* @param {Object} templateAttrs The shared attribute function
|
13908
14093
|
* @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the
|
13909
14094
|
* scope argument is auto-generated to the new child of the transcluded parent scope.
|
13910
|
-
* @param {
|
13911
|
-
* argument has the root jqLite array so that we can replace
|
14095
|
+
* @param {JQLite} jqCollection If we are working on the root of the compile tree then this
|
14096
|
+
* argument has the root jqLite array so that we can replace nodes on it.
|
13912
14097
|
* @returns linkFn
|
13913
14098
|
*/
|
13914
|
-
function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,
|
14099
|
+
function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, jqCollection) {
|
13915
14100
|
var terminalPriority = -Number.MAX_VALUE,
|
13916
14101
|
preLinkFns = [],
|
13917
14102
|
postLinkFns = [],
|
@@ -13965,7 +14150,7 @@ function $CompileProvider($provide) {
|
|
13965
14150
|
$compileNode = templateAttrs.$$element =
|
13966
14151
|
jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));
|
13967
14152
|
compileNode = $compileNode[0];
|
13968
|
-
replaceWith(
|
14153
|
+
replaceWith(jqCollection, jqLite($template[0]), compileNode);
|
13969
14154
|
childTranscludeFn = compile($template, transcludeFn, terminalPriority);
|
13970
14155
|
} else {
|
13971
14156
|
$template = jqLite(JQLiteClone(compileNode)).contents();
|
@@ -13994,7 +14179,7 @@ function $CompileProvider($provide) {
|
|
13994
14179
|
throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);
|
13995
14180
|
}
|
13996
14181
|
|
13997
|
-
replaceWith(
|
14182
|
+
replaceWith(jqCollection, $compileNode, compileNode);
|
13998
14183
|
|
13999
14184
|
var newTemplateAttrs = {$attr: {}};
|
14000
14185
|
|
@@ -14022,7 +14207,7 @@ function $CompileProvider($provide) {
|
|
14022
14207
|
assertNoDuplicate('template', templateDirective, directive, $compileNode);
|
14023
14208
|
templateDirective = directive;
|
14024
14209
|
nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),
|
14025
|
-
nodeLinkFn, $compileNode, templateAttrs,
|
14210
|
+
nodeLinkFn, $compileNode, templateAttrs, jqCollection, directive.replace,
|
14026
14211
|
childTranscludeFn);
|
14027
14212
|
ii = directives.length;
|
14028
14213
|
} else if (directive.compile) {
|
@@ -14163,7 +14348,7 @@ function $CompileProvider($provide) {
|
|
14163
14348
|
parentGet = $parse(attrs[attrName]);
|
14164
14349
|
scope[scopeName] = function(locals) {
|
14165
14350
|
return parentGet(parentScope, locals);
|
14166
|
-
}
|
14351
|
+
};
|
14167
14352
|
break;
|
14168
14353
|
}
|
14169
14354
|
|
@@ -14562,7 +14747,8 @@ function directiveLinkingFn(
|
|
14562
14747
|
* {@link ng.$controllerProvider#register register} method.
|
14563
14748
|
*/
|
14564
14749
|
function $ControllerProvider() {
|
14565
|
-
var controllers = {}
|
14750
|
+
var controllers = {},
|
14751
|
+
CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
|
14566
14752
|
|
14567
14753
|
|
14568
14754
|
/**
|
@@ -14607,17 +14793,32 @@ function $ControllerProvider() {
|
|
14607
14793
|
* a service, so that one can override this service with {@link https://gist.github.com/1649788
|
14608
14794
|
* BC version}.
|
14609
14795
|
*/
|
14610
|
-
return function(
|
14611
|
-
|
14612
|
-
|
14613
|
-
|
14614
|
-
|
14615
|
-
|
14616
|
-
|
14617
|
-
|
14796
|
+
return function(expression, locals) {
|
14797
|
+
var instance, match, constructor, identifier;
|
14798
|
+
|
14799
|
+
if(isString(expression)) {
|
14800
|
+
match = expression.match(CNTRL_REG),
|
14801
|
+
constructor = match[1],
|
14802
|
+
identifier = match[3];
|
14803
|
+
expression = controllers.hasOwnProperty(constructor)
|
14804
|
+
? controllers[constructor]
|
14805
|
+
: getter(locals.$scope, constructor, true) || getter($window, constructor, true);
|
14806
|
+
|
14807
|
+
assertArgFn(expression, constructor, true);
|
14808
|
+
}
|
14809
|
+
|
14810
|
+
instance = $injector.instantiate(expression, locals);
|
14811
|
+
|
14812
|
+
if (identifier) {
|
14813
|
+
if (typeof locals.$scope !== 'object') {
|
14814
|
+
throw new Error('Can not export controller as "' + identifier + '". ' +
|
14815
|
+
'No scope object provided!');
|
14816
|
+
}
|
14817
|
+
|
14818
|
+
locals.$scope[identifier] = instance;
|
14618
14819
|
}
|
14619
14820
|
|
14620
|
-
return
|
14821
|
+
return instance;
|
14621
14822
|
};
|
14622
14823
|
}];
|
14623
14824
|
}
|
@@ -14656,7 +14857,7 @@ function $DocumentProvider(){
|
|
14656
14857
|
*
|
14657
14858
|
*/
|
14658
14859
|
function $ExceptionHandlerProvider() {
|
14659
|
-
this.$get = ['$log', function($log){
|
14860
|
+
this.$get = ['$log', function($log) {
|
14660
14861
|
return function(exception, cause) {
|
14661
14862
|
$log.error.apply($log, arguments);
|
14662
14863
|
};
|
@@ -14850,9 +15051,8 @@ function $InterpolateProvider() {
|
|
14850
15051
|
}];
|
14851
15052
|
}
|
14852
15053
|
|
14853
|
-
var
|
14854
|
-
PATH_MATCH = /^([^\?#]*)
|
14855
|
-
HASH_MATCH = PATH_MATCH,
|
15054
|
+
var SERVER_MATCH = /^([^:]+):\/\/(\w+:{0,1}\w*@)?(\{?[\w\.-]*\}?)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/,
|
15055
|
+
PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/,
|
14856
15056
|
DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};
|
14857
15057
|
|
14858
15058
|
|
@@ -14873,30 +15073,23 @@ function encodePath(path) {
|
|
14873
15073
|
return segments.join('/');
|
14874
15074
|
}
|
14875
15075
|
|
14876
|
-
function stripHash(url) {
|
14877
|
-
return url.split('#')[0];
|
14878
|
-
}
|
14879
|
-
|
14880
|
-
|
14881
15076
|
function matchUrl(url, obj) {
|
14882
|
-
var match =
|
15077
|
+
var match = SERVER_MATCH.exec(url);
|
14883
15078
|
|
14884
|
-
|
14885
|
-
|
14886
|
-
|
14887
|
-
|
14888
|
-
path: match[6] || '/',
|
14889
|
-
search: match[8],
|
14890
|
-
hash: match[10]
|
14891
|
-
};
|
15079
|
+
obj.$$protocol = match[1];
|
15080
|
+
obj.$$host = match[3];
|
15081
|
+
obj.$$port = int(match[5]) || DEFAULT_PORTS[match[1]] || null;
|
15082
|
+
}
|
14892
15083
|
|
14893
|
-
|
14894
|
-
|
14895
|
-
|
14896
|
-
|
14897
|
-
|
15084
|
+
function matchAppUrl(url, obj) {
|
15085
|
+
var match = PATH_MATCH.exec(url);
|
15086
|
+
|
15087
|
+
obj.$$path = decodeURIComponent(match[1]);
|
15088
|
+
obj.$$search = parseKeyValue(match[3]);
|
15089
|
+
obj.$$hash = decodeURIComponent(match[5] || '');
|
14898
15090
|
|
14899
|
-
|
15091
|
+
// make sure path starts with '/';
|
15092
|
+
if (obj.$$path && obj.$$path.charAt(0) != '/') obj.$$path = '/' + obj.$$path;
|
14900
15093
|
}
|
14901
15094
|
|
14902
15095
|
|
@@ -14904,77 +15097,62 @@ function composeProtocolHostPort(protocol, host, port) {
|
|
14904
15097
|
return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);
|
14905
15098
|
}
|
14906
15099
|
|
14907
|
-
|
14908
|
-
|
14909
|
-
|
15100
|
+
/**
|
15101
|
+
*
|
15102
|
+
* @param {string} begin
|
15103
|
+
* @param {string} whole
|
15104
|
+
* @param {string} otherwise
|
15105
|
+
* @returns {string} returns text from whole after begin or otherwise if it does not begin with expected string.
|
15106
|
+
*/
|
15107
|
+
function beginsWith(begin, whole, otherwise) {
|
15108
|
+
return whole.indexOf(begin) == 0 ? whole.substr(begin.length) : otherwise;
|
14910
15109
|
}
|
14911
15110
|
|
14912
15111
|
|
14913
|
-
function
|
14914
|
-
var
|
14915
|
-
|
14916
|
-
// already html5 url
|
14917
|
-
if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||
|
14918
|
-
match.hash.indexOf(hashPrefix) !== 0) {
|
14919
|
-
return url;
|
14920
|
-
// convert hashbang url -> html5 url
|
14921
|
-
} else {
|
14922
|
-
return composeProtocolHostPort(match.protocol, match.host, match.port) +
|
14923
|
-
pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);
|
14924
|
-
}
|
15112
|
+
function stripHash(url) {
|
15113
|
+
var index = url.indexOf('#');
|
15114
|
+
return index == -1 ? url : url.substr(0, index);
|
14925
15115
|
}
|
14926
15116
|
|
14927
15117
|
|
14928
|
-
function
|
14929
|
-
|
14930
|
-
|
14931
|
-
// already hashbang url
|
14932
|
-
if (decodeURIComponent(match.path) == basePath && !isUndefined(match.hash) &&
|
14933
|
-
match.hash.indexOf(hashPrefix) === 0) {
|
14934
|
-
return url;
|
14935
|
-
// convert html5 url -> hashbang url
|
14936
|
-
} else {
|
14937
|
-
var search = match.search && '?' + match.search || '',
|
14938
|
-
hash = match.hash && '#' + match.hash || '',
|
14939
|
-
pathPrefix = pathPrefixFromBase(basePath),
|
14940
|
-
path = match.path.substr(pathPrefix.length);
|
14941
|
-
|
14942
|
-
if (match.path.indexOf(pathPrefix) !== 0) {
|
14943
|
-
throw Error('Invalid url "' + url + '", missing path prefix "' + pathPrefix + '" !');
|
14944
|
-
}
|
15118
|
+
function stripFile(url) {
|
15119
|
+
return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
|
15120
|
+
}
|
14945
15121
|
|
14946
|
-
|
14947
|
-
|
14948
|
-
|
15122
|
+
/* return the server only */
|
15123
|
+
function serverBase(url) {
|
15124
|
+
return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));
|
14949
15125
|
}
|
14950
15126
|
|
14951
15127
|
|
14952
15128
|
/**
|
14953
|
-
*
|
15129
|
+
* LocationHtml5Url represents an url
|
14954
15130
|
* This object is exposed as $location service when HTML5 mode is enabled and supported
|
14955
15131
|
*
|
14956
15132
|
* @constructor
|
14957
|
-
* @param {string}
|
14958
|
-
* @param {string}
|
15133
|
+
* @param {string} appBase application base URL
|
15134
|
+
* @param {string} basePrefix url path prefix
|
14959
15135
|
*/
|
14960
|
-
function
|
14961
|
-
|
14962
|
-
|
15136
|
+
function LocationHtml5Url(appBase, basePrefix) {
|
15137
|
+
basePrefix = basePrefix || '';
|
15138
|
+
var appBaseNoFile = stripFile(appBase);
|
14963
15139
|
/**
|
14964
15140
|
* Parse given html5 (regular) url string into properties
|
14965
15141
|
* @param {string} newAbsoluteUrl HTML5 url
|
14966
15142
|
* @private
|
14967
15143
|
*/
|
14968
|
-
this.$$parse = function(
|
14969
|
-
var
|
14970
|
-
|
14971
|
-
|
14972
|
-
|
15144
|
+
this.$$parse = function(url) {
|
15145
|
+
var parsed = {}
|
15146
|
+
matchUrl(url, parsed);
|
15147
|
+
var pathUrl = beginsWith(appBaseNoFile, url);
|
15148
|
+
if (!isString(pathUrl)) {
|
15149
|
+
throw Error('Invalid url "' + url + '", missing path prefix "' + appBaseNoFile + '".');
|
15150
|
+
}
|
15151
|
+
matchAppUrl(pathUrl, parsed);
|
15152
|
+
extend(this, parsed);
|
15153
|
+
if (!this.$$path) {
|
15154
|
+
this.$$path = '/';
|
14973
15155
|
}
|
14974
|
-
|
14975
|
-
this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));
|
14976
|
-
this.$$search = parseKeyValue(match.search);
|
14977
|
-
this.$$hash = match.hash && decodeURIComponent(match.hash) || '';
|
14978
15156
|
|
14979
15157
|
this.$$compose();
|
14980
15158
|
};
|
@@ -14988,19 +15166,25 @@ function LocationUrl(url, pathPrefix, appBaseUrl) {
|
|
14988
15166
|
hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
|
14989
15167
|
|
14990
15168
|
this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
|
14991
|
-
this.$$absUrl =
|
14992
|
-
pathPrefix + this.$$url;
|
15169
|
+
this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'
|
14993
15170
|
};
|
14994
15171
|
|
15172
|
+
this.$$rewrite = function(url) {
|
15173
|
+
var appUrl, prevAppUrl;
|
14995
15174
|
|
14996
|
-
|
14997
|
-
|
14998
|
-
|
15175
|
+
if ( (appUrl = beginsWith(appBase, url)) !== undefined ) {
|
15176
|
+
prevAppUrl = appUrl;
|
15177
|
+
if ( (appUrl = beginsWith(basePrefix, appUrl)) !== undefined ) {
|
15178
|
+
return appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
|
15179
|
+
} else {
|
15180
|
+
return appBase + prevAppUrl;
|
15181
|
+
}
|
15182
|
+
} else if ( (appUrl = beginsWith(appBaseNoFile, url)) !== undefined ) {
|
15183
|
+
return appBaseNoFile + appUrl;
|
15184
|
+
} else if (appBaseNoFile == url + '/') {
|
15185
|
+
return appBaseNoFile;
|
14999
15186
|
}
|
15000
15187
|
}
|
15001
|
-
|
15002
|
-
|
15003
|
-
this.$$parse(url);
|
15004
15188
|
}
|
15005
15189
|
|
15006
15190
|
|
@@ -15009,11 +15193,11 @@ function LocationUrl(url, pathPrefix, appBaseUrl) {
|
|
15009
15193
|
* This object is exposed as $location service when html5 history api is disabled or not supported
|
15010
15194
|
*
|
15011
15195
|
* @constructor
|
15012
|
-
* @param {string}
|
15013
|
-
* @param {string} hashPrefix
|
15196
|
+
* @param {string} appBase application base URL
|
15197
|
+
* @param {string} hashPrefix hashbang prefix
|
15014
15198
|
*/
|
15015
|
-
function LocationHashbangUrl(
|
15016
|
-
var
|
15199
|
+
function LocationHashbangUrl(appBase, hashPrefix) {
|
15200
|
+
var appBaseNoFile = stripFile(appBase);
|
15017
15201
|
|
15018
15202
|
/**
|
15019
15203
|
* Parse given hashbang url into properties
|
@@ -15021,24 +15205,16 @@ function LocationHashbangUrl(url, hashPrefix, appBaseUrl) {
|
|
15021
15205
|
* @private
|
15022
15206
|
*/
|
15023
15207
|
this.$$parse = function(url) {
|
15024
|
-
|
15025
|
-
|
15026
|
-
|
15027
|
-
|
15028
|
-
throw Error('Invalid url "' + url + '", missing hash prefix "' + hashPrefix + '" !');
|
15208
|
+
matchUrl(url, this);
|
15209
|
+
var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
|
15210
|
+
if (!isString(withoutBaseUrl)) {
|
15211
|
+
throw new Error('Invalid url "' + url + '", does not start with "' + appBase + '".');
|
15029
15212
|
}
|
15030
|
-
|
15031
|
-
|
15032
|
-
|
15033
|
-
if (match[1]) {
|
15034
|
-
this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);
|
15035
|
-
} else {
|
15036
|
-
this.$$path = '';
|
15213
|
+
var withoutHashUrl = withoutBaseUrl.charAt(0) == '#' ? beginsWith(hashPrefix, withoutBaseUrl) : withoutBaseUrl;
|
15214
|
+
if (!isString(withoutHashUrl)) {
|
15215
|
+
throw new Error('Invalid url "' + url + '", missing hash prefix "' + hashPrefix + '".');
|
15037
15216
|
}
|
15038
|
-
|
15039
|
-
this.$$search = parseKeyValue(match[3]);
|
15040
|
-
this.$$hash = match[5] && decodeURIComponent(match[5]) || '';
|
15041
|
-
|
15217
|
+
matchAppUrl(withoutHashUrl, this);
|
15042
15218
|
this.$$compose();
|
15043
15219
|
};
|
15044
15220
|
|
@@ -15051,22 +15227,48 @@ function LocationHashbangUrl(url, hashPrefix, appBaseUrl) {
|
|
15051
15227
|
hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
|
15052
15228
|
|
15053
15229
|
this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
|
15054
|
-
this.$$absUrl =
|
15055
|
-
basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');
|
15230
|
+
this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');
|
15056
15231
|
};
|
15057
15232
|
|
15058
|
-
this.$$
|
15059
|
-
if(
|
15060
|
-
return
|
15233
|
+
this.$$rewrite = function(url) {
|
15234
|
+
if(stripHash(appBase) == stripHash(url)) {
|
15235
|
+
return url;
|
15061
15236
|
}
|
15062
15237
|
}
|
15238
|
+
}
|
15239
|
+
|
15240
|
+
|
15241
|
+
/**
|
15242
|
+
* LocationHashbangUrl represents url
|
15243
|
+
* This object is exposed as $location service when html5 history api is enabled but the browser
|
15244
|
+
* does not support it.
|
15245
|
+
*
|
15246
|
+
* @constructor
|
15247
|
+
* @param {string} appBase application base URL
|
15248
|
+
* @param {string} hashPrefix hashbang prefix
|
15249
|
+
*/
|
15250
|
+
function LocationHashbangInHtml5Url(appBase, hashPrefix) {
|
15251
|
+
LocationHashbangUrl.apply(this, arguments);
|
15063
15252
|
|
15253
|
+
var appBaseNoFile = stripFile(appBase);
|
15064
15254
|
|
15065
|
-
this.$$
|
15255
|
+
this.$$rewrite = function(url) {
|
15256
|
+
var appUrl;
|
15257
|
+
|
15258
|
+
if ( appBase == stripHash(url) ) {
|
15259
|
+
return url;
|
15260
|
+
} else if ( (appUrl = beginsWith(appBaseNoFile, url)) ) {
|
15261
|
+
return appBase + hashPrefix + appUrl;
|
15262
|
+
} else if ( appBaseNoFile === url + '/') {
|
15263
|
+
return appBaseNoFile;
|
15264
|
+
}
|
15265
|
+
}
|
15066
15266
|
}
|
15067
15267
|
|
15068
15268
|
|
15069
|
-
|
15269
|
+
LocationHashbangInHtml5Url.prototype =
|
15270
|
+
LocationHashbangUrl.prototype =
|
15271
|
+
LocationHtml5Url.prototype = {
|
15070
15272
|
|
15071
15273
|
/**
|
15072
15274
|
* Has any change been replacing ?
|
@@ -15248,21 +15450,6 @@ LocationUrl.prototype = {
|
|
15248
15450
|
}
|
15249
15451
|
};
|
15250
15452
|
|
15251
|
-
LocationHashbangUrl.prototype = inherit(LocationUrl.prototype);
|
15252
|
-
|
15253
|
-
function LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {
|
15254
|
-
LocationHashbangUrl.apply(this, arguments);
|
15255
|
-
|
15256
|
-
|
15257
|
-
this.$$rewriteAppUrl = function(absoluteLinkUrl) {
|
15258
|
-
if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {
|
15259
|
-
return appBaseUrl + baseExtra + '#' + hashPrefix + absoluteLinkUrl.substr(appBaseUrl.length);
|
15260
|
-
}
|
15261
|
-
}
|
15262
|
-
}
|
15263
|
-
|
15264
|
-
LocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);
|
15265
|
-
|
15266
15453
|
function locationGetter(property) {
|
15267
15454
|
return function() {
|
15268
15455
|
return this[property];
|
@@ -15359,37 +15546,20 @@ function $LocationProvider(){
|
|
15359
15546
|
this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',
|
15360
15547
|
function( $rootScope, $browser, $sniffer, $rootElement) {
|
15361
15548
|
var $location,
|
15362
|
-
|
15363
|
-
|
15364
|
-
|
15365
|
-
|
15366
|
-
appBaseUrl;
|
15549
|
+
LocationMode,
|
15550
|
+
baseHref = $browser.baseHref(),
|
15551
|
+
initialUrl = $browser.url(),
|
15552
|
+
appBase;
|
15367
15553
|
|
15368
15554
|
if (html5Mode) {
|
15369
|
-
|
15370
|
-
|
15371
|
-
appBaseUrl =
|
15372
|
-
composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +
|
15373
|
-
pathPrefix + '/';
|
15374
|
-
|
15375
|
-
if ($sniffer.history) {
|
15376
|
-
$location = new LocationUrl(
|
15377
|
-
convertToHtml5Url(initUrl, basePath, hashPrefix),
|
15378
|
-
pathPrefix, appBaseUrl);
|
15379
|
-
} else {
|
15380
|
-
$location = new LocationHashbangInHtml5Url(
|
15381
|
-
convertToHashbangUrl(initUrl, basePath, hashPrefix),
|
15382
|
-
hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));
|
15383
|
-
}
|
15555
|
+
appBase = baseHref ? serverBase(initialUrl) + baseHref : initialUrl;
|
15556
|
+
LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;
|
15384
15557
|
} else {
|
15385
|
-
|
15386
|
-
|
15387
|
-
(initUrlParts.path || '') +
|
15388
|
-
(initUrlParts.search ? ('?' + initUrlParts.search) : '') +
|
15389
|
-
'#' + hashPrefix + '/';
|
15390
|
-
|
15391
|
-
$location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);
|
15558
|
+
appBase = stripHash(initialUrl);
|
15559
|
+
LocationMode = LocationHashbangUrl;
|
15392
15560
|
}
|
15561
|
+
$location = new LocationMode(appBase, '#' + hashPrefix);
|
15562
|
+
$location.$$parse($location.$$rewrite(initialUrl));
|
15393
15563
|
|
15394
15564
|
$rootElement.bind('click', function(event) {
|
15395
15565
|
// TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
|
@@ -15405,28 +15575,34 @@ function $LocationProvider(){
|
|
15405
15575
|
if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
|
15406
15576
|
}
|
15407
15577
|
|
15408
|
-
var absHref = elm.prop('href')
|
15409
|
-
|
15578
|
+
var absHref = elm.prop('href');
|
15579
|
+
var rewrittenUrl = $location.$$rewrite(absHref);
|
15410
15580
|
|
15411
|
-
if (absHref && !elm.attr('target') && rewrittenUrl) {
|
15412
|
-
// update location manually
|
15413
|
-
$location.$$parse(rewrittenUrl);
|
15414
|
-
$rootScope.$apply();
|
15581
|
+
if (absHref && !elm.attr('target') && rewrittenUrl && !event.isDefaultPrevented()) {
|
15415
15582
|
event.preventDefault();
|
15416
|
-
|
15417
|
-
|
15583
|
+
if (rewrittenUrl != $browser.url()) {
|
15584
|
+
// update location manually
|
15585
|
+
$location.$$parse(rewrittenUrl);
|
15586
|
+
$rootScope.$apply();
|
15587
|
+
// hack to work around FF6 bug 684208 when scenario runner clicks on links
|
15588
|
+
window.angular['ff-684208-preventDefault'] = true;
|
15589
|
+
}
|
15418
15590
|
}
|
15419
15591
|
});
|
15420
15592
|
|
15421
15593
|
|
15422
15594
|
// rewrite hashbang url <> html5 url
|
15423
|
-
if ($location.absUrl() !=
|
15595
|
+
if ($location.absUrl() != initialUrl) {
|
15424
15596
|
$browser.url($location.absUrl(), true);
|
15425
15597
|
}
|
15426
15598
|
|
15427
15599
|
// update $location when $browser url changes
|
15428
15600
|
$browser.onUrlChange(function(newUrl) {
|
15429
15601
|
if ($location.absUrl() != newUrl) {
|
15602
|
+
if ($rootScope.$broadcast('$locationChangeStart', newUrl, $location.absUrl()).defaultPrevented) {
|
15603
|
+
$browser.url($location.absUrl());
|
15604
|
+
return;
|
15605
|
+
}
|
15430
15606
|
$rootScope.$evalAsync(function() {
|
15431
15607
|
var oldUrl = $location.absUrl();
|
15432
15608
|
|
@@ -15683,7 +15859,7 @@ function lex(text, csp){
|
|
15683
15859
|
(token=tokens[tokens.length-1])) {
|
15684
15860
|
token.json = token.text.indexOf('.') == -1;
|
15685
15861
|
}
|
15686
|
-
} else if (is('(){}[]
|
15862
|
+
} else if (is('(){}[].,;:?')) {
|
15687
15863
|
tokens.push({
|
15688
15864
|
index:index,
|
15689
15865
|
text:ch,
|
@@ -15787,10 +15963,10 @@ function lex(text, csp){
|
|
15787
15963
|
function readIdent() {
|
15788
15964
|
var ident = "",
|
15789
15965
|
start = index,
|
15790
|
-
lastDot, peekIndex, methodName;
|
15966
|
+
lastDot, peekIndex, methodName, ch;
|
15791
15967
|
|
15792
15968
|
while (index < text.length) {
|
15793
|
-
|
15969
|
+
ch = text.charAt(index);
|
15794
15970
|
if (ch == '.' || isIdent(ch) || isNumber(ch)) {
|
15795
15971
|
if (ch == '.') lastDot = index;
|
15796
15972
|
ident += ch;
|
@@ -15804,7 +15980,7 @@ function lex(text, csp){
|
|
15804
15980
|
if (lastDot) {
|
15805
15981
|
peekIndex = index;
|
15806
15982
|
while(peekIndex < text.length) {
|
15807
|
-
|
15983
|
+
ch = text.charAt(peekIndex);
|
15808
15984
|
if (ch == '(') {
|
15809
15985
|
methodName = ident.substr(lastDot - start + 1);
|
15810
15986
|
ident = ident.substr(0, lastDot - start);
|
@@ -15984,6 +16160,14 @@ function parser(text, json, $filter, csp){
|
|
15984
16160
|
});
|
15985
16161
|
}
|
15986
16162
|
|
16163
|
+
function ternaryFn(left, middle, right){
|
16164
|
+
return extend(function(self, locals){
|
16165
|
+
return left(self, locals) ? middle(self, locals) : right(self, locals);
|
16166
|
+
}, {
|
16167
|
+
constant: left.constant && middle.constant && right.constant
|
16168
|
+
});
|
16169
|
+
}
|
16170
|
+
|
15987
16171
|
function binaryFn(left, fn, right) {
|
15988
16172
|
return extend(function(self, locals) {
|
15989
16173
|
return fn(self, locals, left, right);
|
@@ -16054,7 +16238,7 @@ function parser(text, json, $filter, csp){
|
|
16054
16238
|
}
|
16055
16239
|
|
16056
16240
|
function _assignment() {
|
16057
|
-
var left =
|
16241
|
+
var left = ternary();
|
16058
16242
|
var right;
|
16059
16243
|
var token;
|
16060
16244
|
if ((token = expect('='))) {
|
@@ -16062,15 +16246,33 @@ function parser(text, json, $filter, csp){
|
|
16062
16246
|
throwError("implies assignment but [" +
|
16063
16247
|
text.substring(0, token.index) + "] can not be assigned to", token);
|
16064
16248
|
}
|
16065
|
-
right =
|
16066
|
-
return function(
|
16067
|
-
return left.assign(
|
16249
|
+
right = ternary();
|
16250
|
+
return function(scope, locals){
|
16251
|
+
return left.assign(scope, right(scope, locals), locals);
|
16068
16252
|
};
|
16069
16253
|
} else {
|
16070
16254
|
return left;
|
16071
16255
|
}
|
16072
16256
|
}
|
16073
16257
|
|
16258
|
+
function ternary() {
|
16259
|
+
var left = logicalOR();
|
16260
|
+
var middle;
|
16261
|
+
var token;
|
16262
|
+
if((token = expect('?'))){
|
16263
|
+
middle = ternary();
|
16264
|
+
if((token = expect(':'))){
|
16265
|
+
return ternaryFn(left, middle, ternary());
|
16266
|
+
}
|
16267
|
+
else {
|
16268
|
+
throwError('expected :', token);
|
16269
|
+
}
|
16270
|
+
}
|
16271
|
+
else {
|
16272
|
+
return left;
|
16273
|
+
}
|
16274
|
+
}
|
16275
|
+
|
16074
16276
|
function logicalOR() {
|
16075
16277
|
var left = logicalAND();
|
16076
16278
|
var token;
|
@@ -16184,12 +16386,12 @@ function parser(text, json, $filter, csp){
|
|
16184
16386
|
var field = expect().text;
|
16185
16387
|
var getter = getterFn(field, csp);
|
16186
16388
|
return extend(
|
16187
|
-
function(
|
16188
|
-
return getter(object(
|
16389
|
+
function(scope, locals, self) {
|
16390
|
+
return getter(self || object(scope, locals), locals);
|
16189
16391
|
},
|
16190
16392
|
{
|
16191
|
-
assign:function(
|
16192
|
-
return setter(object(
|
16393
|
+
assign:function(scope, value, locals) {
|
16394
|
+
return setter(object(scope, locals), field, value);
|
16193
16395
|
}
|
16194
16396
|
}
|
16195
16397
|
);
|
@@ -16230,14 +16432,14 @@ function parser(text, json, $filter, csp){
|
|
16230
16432
|
} while (expect(','));
|
16231
16433
|
}
|
16232
16434
|
consume(')');
|
16233
|
-
return function(
|
16435
|
+
return function(scope, locals){
|
16234
16436
|
var args = [],
|
16235
|
-
context = contextGetter ? contextGetter(
|
16437
|
+
context = contextGetter ? contextGetter(scope, locals) : scope;
|
16236
16438
|
|
16237
16439
|
for ( var i = 0; i < argsFn.length; i++) {
|
16238
|
-
args.push(argsFn[i](
|
16440
|
+
args.push(argsFn[i](scope, locals));
|
16239
16441
|
}
|
16240
|
-
var fnPtr = fn(
|
16442
|
+
var fnPtr = fn(scope, locals, context) || noop;
|
16241
16443
|
// IE stupidity!
|
16242
16444
|
return fnPtr.apply
|
16243
16445
|
? fnPtr.apply(context, args)
|
@@ -16291,8 +16493,7 @@ function parser(text, json, $filter, csp){
|
|
16291
16493
|
var object = {};
|
16292
16494
|
for ( var i = 0; i < keyValues.length; i++) {
|
16293
16495
|
var keyValue = keyValues[i];
|
16294
|
-
|
16295
|
-
object[keyValue.key] = value;
|
16496
|
+
object[keyValue.key] = keyValue.value(self, locals);
|
16296
16497
|
}
|
16297
16498
|
return object;
|
16298
16499
|
}, {
|
@@ -16417,7 +16618,7 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4) {
|
|
16417
16618
|
}
|
16418
16619
|
return pathVal;
|
16419
16620
|
};
|
16420
|
-
}
|
16621
|
+
}
|
16421
16622
|
|
16422
16623
|
function getterFn(path, csp) {
|
16423
16624
|
if (getterFnCache.hasOwnProperty(path)) {
|
@@ -16432,7 +16633,7 @@ function getterFn(path, csp) {
|
|
16432
16633
|
fn = (pathKeysLength < 6)
|
16433
16634
|
? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])
|
16434
16635
|
: function(scope, locals) {
|
16435
|
-
var i = 0, val
|
16636
|
+
var i = 0, val;
|
16436
16637
|
do {
|
16437
16638
|
val = cspSafeGetterFn(
|
16438
16639
|
pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]
|
@@ -16620,6 +16821,11 @@ function $ParseProvider() {
|
|
16620
16821
|
* This method *returns a new promise* which is resolved or rejected via the return value of the
|
16621
16822
|
* `successCallback` or `errorCallback`.
|
16622
16823
|
*
|
16824
|
+
* - `always(callback)` – allows you to observe either the fulfillment or rejection of a promise,
|
16825
|
+
* but to do so without modifying the final value. This is useful to release resources or do some
|
16826
|
+
* clean-up that needs to be done whether the promise was rejected or resolved. See the [full
|
16827
|
+
* specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for
|
16828
|
+
* more information.
|
16623
16829
|
*
|
16624
16830
|
* # Chaining promises
|
16625
16831
|
*
|
@@ -16650,7 +16856,7 @@ function $ParseProvider() {
|
|
16650
16856
|
* models and avoiding unnecessary browser repaints, which would result in flickering UI.
|
16651
16857
|
* - $q promises are recognized by the templating engine in angular, which means that in templates
|
16652
16858
|
* you can treat promises attached to a scope as if they were the resulting values.
|
16653
|
-
* - Q has many more features
|
16859
|
+
* - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains
|
16654
16860
|
* all the important functionality needed for common async tasks.
|
16655
16861
|
*
|
16656
16862
|
* # Testing
|
@@ -16765,6 +16971,42 @@ function qFactory(nextTick, exceptionHandler) {
|
|
16765
16971
|
}
|
16766
16972
|
|
16767
16973
|
return result.promise;
|
16974
|
+
},
|
16975
|
+
always: function(callback) {
|
16976
|
+
|
16977
|
+
function makePromise(value, resolved) {
|
16978
|
+
var result = defer();
|
16979
|
+
if (resolved) {
|
16980
|
+
result.resolve(value);
|
16981
|
+
} else {
|
16982
|
+
result.reject(value);
|
16983
|
+
}
|
16984
|
+
return result.promise;
|
16985
|
+
}
|
16986
|
+
|
16987
|
+
function handleCallback(value, isResolved) {
|
16988
|
+
var callbackOutput = null;
|
16989
|
+
try {
|
16990
|
+
callbackOutput = (callback ||defaultCallback)();
|
16991
|
+
} catch(e) {
|
16992
|
+
return makePromise(e, false);
|
16993
|
+
}
|
16994
|
+
if (callbackOutput && callbackOutput.then) {
|
16995
|
+
return callbackOutput.then(function() {
|
16996
|
+
return makePromise(value, isResolved);
|
16997
|
+
}, function(error) {
|
16998
|
+
return makePromise(error, false);
|
16999
|
+
});
|
17000
|
+
} else {
|
17001
|
+
return makePromise(value, isResolved);
|
17002
|
+
}
|
17003
|
+
}
|
17004
|
+
|
17005
|
+
return this.then(function(value) {
|
17006
|
+
return handleCallback(value, true);
|
17007
|
+
}, function(error) {
|
17008
|
+
return handleCallback(error, false);
|
17009
|
+
});
|
16768
17010
|
}
|
16769
17011
|
}
|
16770
17012
|
};
|
@@ -16845,10 +17087,7 @@ function qFactory(nextTick, exceptionHandler) {
|
|
16845
17087
|
* the promise comes from a source that can't be trusted.
|
16846
17088
|
*
|
16847
17089
|
* @param {*} value Value or a promise
|
16848
|
-
* @returns {Promise} Returns a
|
16849
|
-
* each value corresponding to the promise at the same index in the `promises` array. If any of
|
16850
|
-
* the promises is resolved with a rejection, this resulting promise will be resolved with the
|
16851
|
-
* same rejection.
|
17090
|
+
* @returns {Promise} Returns a promise of the passed value or promise
|
16852
17091
|
*/
|
16853
17092
|
var when = function(value, callback, errback) {
|
16854
17093
|
var result = defer(),
|
@@ -16987,6 +17226,8 @@ function $RouteProvider(){
|
|
16987
17226
|
* - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly
|
16988
17227
|
* created scope or the name of a {@link angular.Module#controller registered controller}
|
16989
17228
|
* if passed as a string.
|
17229
|
+
* - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be
|
17230
|
+
* published to scope under the `controllerAs` name.
|
16990
17231
|
* - `template` – `{string=|function()=}` – html template as a string or function that returns
|
16991
17232
|
* an html template as a string which should be used by {@link ng.directive:ngView ngView} or
|
16992
17233
|
* {@link ng.directive:ngInclude ngInclude} directives.
|
@@ -17481,22 +17722,22 @@ function $RouteParamsProvider() {
|
|
17481
17722
|
/**
|
17482
17723
|
* DESIGN NOTES
|
17483
17724
|
*
|
17484
|
-
* The design decisions behind the scope
|
17725
|
+
* The design decisions behind the scope are heavily favored for speed and memory consumption.
|
17485
17726
|
*
|
17486
17727
|
* The typical use of scope is to watch the expressions, which most of the time return the same
|
17487
17728
|
* value as last time so we optimize the operation.
|
17488
17729
|
*
|
17489
|
-
* Closures construction is expensive
|
17490
|
-
* -
|
17730
|
+
* Closures construction is expensive in terms of speed as well as memory:
|
17731
|
+
* - No closures, instead use prototypical inheritance for API
|
17491
17732
|
* - Internal state needs to be stored on scope directly, which means that private state is
|
17492
17733
|
* exposed as $$____ properties
|
17493
17734
|
*
|
17494
17735
|
* Loop operations are optimized by using while(count--) { ... }
|
17495
17736
|
* - this means that in order to keep the same order of execution as addition we have to add
|
17496
|
-
* items to the array at the
|
17737
|
+
* items to the array at the beginning (shift) instead of at the end (push)
|
17497
17738
|
*
|
17498
17739
|
* Child scopes are created and removed often
|
17499
|
-
* - Using array would be slow since inserts in
|
17740
|
+
* - Using an array would be slow since inserts in middle are expensive so we use linked list
|
17500
17741
|
*
|
17501
17742
|
* There are few watches then a lot of observers. This is why you don't want the observer to be
|
17502
17743
|
* implemented in the same way as watch. Watch requires return of initialization function which
|
@@ -17518,7 +17759,7 @@ function $RouteParamsProvider() {
|
|
17518
17759
|
* @methodOf ng.$rootScopeProvider
|
17519
17760
|
* @description
|
17520
17761
|
*
|
17521
|
-
* Sets the number of digest
|
17762
|
+
* Sets the number of digest iterations the scope should attempt to execute before giving up and
|
17522
17763
|
* assuming that the model is unstable.
|
17523
17764
|
*
|
17524
17765
|
* The current default is 10 iterations.
|
@@ -17854,7 +18095,7 @@ function $RootScopeProvider(){
|
|
17854
18095
|
oldValue = newValue;
|
17855
18096
|
changeDetected++;
|
17856
18097
|
}
|
17857
|
-
} else if (
|
18098
|
+
} else if (isArrayLike(newValue)) {
|
17858
18099
|
if (oldValue !== internalArray) {
|
17859
18100
|
// we are transitioning from something which was not an array into array.
|
17860
18101
|
oldValue = internalArray;
|
@@ -17928,7 +18169,7 @@ function $RootScopeProvider(){
|
|
17928
18169
|
* @function
|
17929
18170
|
*
|
17930
18171
|
* @description
|
17931
|
-
*
|
18172
|
+
* Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.
|
17932
18173
|
* Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the
|
17933
18174
|
* `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are
|
17934
18175
|
* firing. This means that it is possible to get into an infinite loop. This function will throw
|
@@ -18271,7 +18512,7 @@ function $RootScopeProvider(){
|
|
18271
18512
|
* Afterwards, the event traverses upwards toward the root scope and calls all registered
|
18272
18513
|
* listeners along the way. The event will stop propagating if one of the listeners cancels it.
|
18273
18514
|
*
|
18274
|
-
* Any exception
|
18515
|
+
* Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
|
18275
18516
|
* onto the {@link ng.$exceptionHandler $exceptionHandler} service.
|
18276
18517
|
*
|
18277
18518
|
* @param {string} name Event name to emit.
|
@@ -18340,7 +18581,7 @@ function $RootScopeProvider(){
|
|
18340
18581
|
* Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
|
18341
18582
|
* onto the {@link ng.$exceptionHandler $exceptionHandler} service.
|
18342
18583
|
*
|
18343
|
-
* @param {string} name Event name to
|
18584
|
+
* @param {string} name Event name to broadcast.
|
18344
18585
|
* @param {...*} args Optional set of arguments which will be passed onto the event listeners.
|
18345
18586
|
* @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}
|
18346
18587
|
*/
|
@@ -18434,7 +18675,8 @@ function $RootScopeProvider(){
|
|
18434
18675
|
*
|
18435
18676
|
* @property {boolean} history Does the browser support html5 history api ?
|
18436
18677
|
* @property {boolean} hashchange Does the browser support hashchange event ?
|
18437
|
-
* @property {boolean}
|
18678
|
+
* @property {boolean} transitions Does the browser support CSS transition events ?
|
18679
|
+
* @property {boolean} animations Does the browser support CSS animation events ?
|
18438
18680
|
*
|
18439
18681
|
* @description
|
18440
18682
|
* This is very simple implementation of testing browser's features.
|
@@ -18448,6 +18690,7 @@ function $SnifferProvider() {
|
|
18448
18690
|
vendorRegex = /^(Moz|webkit|O|ms)(?=[A-Z])/,
|
18449
18691
|
bodyStyle = document.body && document.body.style,
|
18450
18692
|
transitions = false,
|
18693
|
+
animations = false,
|
18451
18694
|
match;
|
18452
18695
|
|
18453
18696
|
if (bodyStyle) {
|
@@ -18458,7 +18701,8 @@ function $SnifferProvider() {
|
|
18458
18701
|
break;
|
18459
18702
|
}
|
18460
18703
|
}
|
18461
|
-
transitions = !!(vendorPrefix + 'Transition' in bodyStyle);
|
18704
|
+
transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));
|
18705
|
+
animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));
|
18462
18706
|
}
|
18463
18707
|
|
18464
18708
|
|
@@ -18486,7 +18730,8 @@ function $SnifferProvider() {
|
|
18486
18730
|
},
|
18487
18731
|
csp: document.securityPolicy ? document.securityPolicy.isActive : false,
|
18488
18732
|
vendorPrefix: vendorPrefix,
|
18489
|
-
|
18733
|
+
transitions : transitions,
|
18734
|
+
animations : animations
|
18490
18735
|
};
|
18491
18736
|
}];
|
18492
18737
|
}
|
@@ -18507,10 +18752,23 @@ function $SnifferProvider() {
|
|
18507
18752
|
* @example
|
18508
18753
|
<doc:example>
|
18509
18754
|
<doc:source>
|
18510
|
-
<
|
18511
|
-
|
18755
|
+
<script>
|
18756
|
+
function Ctrl($scope, $window) {
|
18757
|
+
$scope.$window = $window;
|
18758
|
+
$scope.greeting = 'Hello, World!';
|
18759
|
+
}
|
18760
|
+
</script>
|
18761
|
+
<div ng-controller="Ctrl">
|
18762
|
+
<input type="text" ng-model="greeting" />
|
18763
|
+
<button ng-click="$window.alert(greeting)">ALERT</button>
|
18764
|
+
</div>
|
18512
18765
|
</doc:source>
|
18513
18766
|
<doc:scenario>
|
18767
|
+
it('should display the greeting in the input box', function() {
|
18768
|
+
input('greeting').enter('Hello, E2E Tests');
|
18769
|
+
// If we click the button it will block the test runner
|
18770
|
+
// element(':button').click();
|
18771
|
+
});
|
18514
18772
|
</doc:scenario>
|
18515
18773
|
</doc:example>
|
18516
18774
|
*/
|
@@ -18570,7 +18828,7 @@ function isSameDomain(requestUrl, locationUrl) {
|
|
18570
18828
|
relativeProtocol: match[2] === undefined || match[2] === ''
|
18571
18829
|
};
|
18572
18830
|
|
18573
|
-
match =
|
18831
|
+
match = SERVER_MATCH.exec(locationUrl);
|
18574
18832
|
var domain2 = {
|
18575
18833
|
protocol: match[1],
|
18576
18834
|
host: match[3],
|
@@ -18641,7 +18899,8 @@ function isSuccess(status) {
|
|
18641
18899
|
function $HttpProvider() {
|
18642
18900
|
var JSON_START = /^\s*(\[|\{[^\{])/,
|
18643
18901
|
JSON_END = /[\}\]]\s*$/,
|
18644
|
-
PROTECTION_PREFIX = /^\)\]\}',?\n
|
18902
|
+
PROTECTION_PREFIX = /^\)\]\}',?\n/,
|
18903
|
+
CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': 'application/json;charset=utf-8'};
|
18645
18904
|
|
18646
18905
|
var defaults = this.defaults = {
|
18647
18906
|
// transform incoming response data
|
@@ -18665,8 +18924,9 @@ function $HttpProvider() {
|
|
18665
18924
|
common: {
|
18666
18925
|
'Accept': 'application/json, text/plain, */*'
|
18667
18926
|
},
|
18668
|
-
post:
|
18669
|
-
put:
|
18927
|
+
post: CONTENT_TYPE_APPLICATION_JSON,
|
18928
|
+
put: CONTENT_TYPE_APPLICATION_JSON,
|
18929
|
+
patch: CONTENT_TYPE_APPLICATION_JSON
|
18670
18930
|
},
|
18671
18931
|
|
18672
18932
|
xsrfCookieName: 'XSRF-TOKEN',
|
@@ -18734,7 +18994,7 @@ function $HttpProvider() {
|
|
18734
18994
|
*
|
18735
18995
|
* @description
|
18736
18996
|
* The `$http` service is a core Angular service that facilitates communication with the remote
|
18737
|
-
* HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest
|
18997
|
+
* HTTP servers via the browser's {@link https://developer.mozilla.org/en/xmlhttprequest
|
18738
18998
|
* XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.
|
18739
18999
|
*
|
18740
19000
|
* For unit testing applications that use `$http` service, see
|
@@ -18744,13 +19004,13 @@ function $HttpProvider() {
|
|
18744
19004
|
* $resource} service.
|
18745
19005
|
*
|
18746
19006
|
* The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by
|
18747
|
-
* the $q service. While for simple usage
|
18748
|
-
* it is important to familiarize yourself with these
|
19007
|
+
* the $q service. While for simple usage patterns this doesn't matter much, for advanced usage
|
19008
|
+
* it is important to familiarize yourself with these APIs and the guarantees they provide.
|
18749
19009
|
*
|
18750
19010
|
*
|
18751
19011
|
* # General usage
|
18752
19012
|
* The `$http` service is a function which takes a single argument — a configuration object —
|
18753
|
-
* that is used to generate an
|
19013
|
+
* that is used to generate an HTTP request and returns a {@link ng.$q promise}
|
18754
19014
|
* with two $http specific methods: `success` and `error`.
|
18755
19015
|
*
|
18756
19016
|
* <pre>
|
@@ -18765,21 +19025,21 @@ function $HttpProvider() {
|
|
18765
19025
|
* });
|
18766
19026
|
* </pre>
|
18767
19027
|
*
|
18768
|
-
* Since the returned value of calling the $http function is a
|
19028
|
+
* Since the returned value of calling the $http function is a `promise`, you can also use
|
18769
19029
|
* the `then` method to register callbacks, and these callbacks will receive a single argument –
|
18770
|
-
* an object representing the response. See the
|
19030
|
+
* an object representing the response. See the API signature and type info below for more
|
18771
19031
|
* details.
|
18772
19032
|
*
|
18773
|
-
* A response status code
|
19033
|
+
* A response status code between 200 and 299 is considered a success status and
|
18774
19034
|
* will result in the success callback being called. Note that if the response is a redirect,
|
18775
19035
|
* XMLHttpRequest will transparently follow it, meaning that the error callback will not be
|
18776
19036
|
* called for such responses.
|
18777
19037
|
*
|
18778
19038
|
* # Shortcut methods
|
18779
19039
|
*
|
18780
|
-
* Since all
|
18781
|
-
* POST
|
18782
|
-
* were created
|
19040
|
+
* Since all invocations of the $http service require passing in an HTTP method and URL, and
|
19041
|
+
* POST/PUT requests require request data to be provided as well, shortcut methods
|
19042
|
+
* were created:
|
18783
19043
|
*
|
18784
19044
|
* <pre>
|
18785
19045
|
* $http.get('/someUrl').success(successCallback);
|
@@ -18798,24 +19058,24 @@ function $HttpProvider() {
|
|
18798
19058
|
*
|
18799
19059
|
* # Setting HTTP Headers
|
18800
19060
|
*
|
18801
|
-
* The $http service will automatically add certain
|
19061
|
+
* The $http service will automatically add certain HTTP headers to all requests. These defaults
|
18802
19062
|
* can be fully configured by accessing the `$httpProvider.defaults.headers` configuration
|
18803
19063
|
* object, which currently contains this default configuration:
|
18804
19064
|
*
|
18805
19065
|
* - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
|
18806
19066
|
* - `Accept: application/json, text/plain, * / *`
|
18807
|
-
* - `$httpProvider.defaults.headers.post`: (header defaults for
|
19067
|
+
* - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)
|
18808
19068
|
* - `Content-Type: application/json`
|
18809
|
-
* - `$httpProvider.defaults.headers.put` (header defaults for
|
19069
|
+
* - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)
|
18810
19070
|
* - `Content-Type: application/json`
|
18811
19071
|
*
|
18812
|
-
* To add or overwrite these defaults, simply add or remove a property from
|
19072
|
+
* To add or overwrite these defaults, simply add or remove a property from these configuration
|
18813
19073
|
* objects. To add headers for an HTTP method other than POST or PUT, simply add a new object
|
18814
|
-
* with
|
19074
|
+
* with the lowercased HTTP method name as the key, e.g.
|
18815
19075
|
* `$httpProvider.defaults.headers.get['My-Header']='value'`.
|
18816
19076
|
*
|
18817
|
-
* Additionally, the defaults can be set at runtime via the `$http.defaults` object in
|
18818
|
-
* fashion
|
19077
|
+
* Additionally, the defaults can be set at runtime via the `$http.defaults` object in the same
|
19078
|
+
* fashion.
|
18819
19079
|
*
|
18820
19080
|
*
|
18821
19081
|
* # Transforming Requests and Responses
|
@@ -18825,54 +19085,54 @@ function $HttpProvider() {
|
|
18825
19085
|
*
|
18826
19086
|
* Request transformations:
|
18827
19087
|
*
|
18828
|
-
* -
|
19088
|
+
* - If the `data` property of the request configuration object contains an object, serialize it into
|
18829
19089
|
* JSON format.
|
18830
19090
|
*
|
18831
19091
|
* Response transformations:
|
18832
19092
|
*
|
18833
|
-
* -
|
18834
|
-
* -
|
19093
|
+
* - If XSRF prefix is detected, strip it (see Security Considerations section below).
|
19094
|
+
* - If JSON response is detected, deserialize it using a JSON parser.
|
18835
19095
|
*
|
18836
19096
|
* To globally augment or override the default transforms, modify the `$httpProvider.defaults.transformRequest` and
|
18837
|
-
* `$httpProvider.defaults.transformResponse` properties
|
19097
|
+
* `$httpProvider.defaults.transformResponse` properties. These properties are by default an
|
18838
19098
|
* array of transform functions, which allows you to `push` or `unshift` a new transformation function into the
|
18839
19099
|
* transformation chain. You can also decide to completely override any default transformations by assigning your
|
18840
19100
|
* transformation functions to these properties directly without the array wrapper.
|
18841
19101
|
*
|
18842
19102
|
* Similarly, to locally override the request/response transforms, augment the `transformRequest` and/or
|
18843
|
-
* `transformResponse` properties of the
|
19103
|
+
* `transformResponse` properties of the configuration object passed into `$http`.
|
18844
19104
|
*
|
18845
19105
|
*
|
18846
19106
|
* # Caching
|
18847
19107
|
*
|
18848
|
-
* To enable caching set the configuration property `cache` to `true`. When the cache is
|
19108
|
+
* To enable caching, set the configuration property `cache` to `true`. When the cache is
|
18849
19109
|
* enabled, `$http` stores the response from the server in local cache. Next time the
|
18850
19110
|
* response is served from the cache without sending a request to the server.
|
18851
19111
|
*
|
18852
19112
|
* Note that even if the response is served from cache, delivery of the data is asynchronous in
|
18853
19113
|
* the same way that real requests are.
|
18854
19114
|
*
|
18855
|
-
* If there are multiple GET requests for the same
|
19115
|
+
* If there are multiple GET requests for the same URL that should be cached using the same
|
18856
19116
|
* cache, but the cache is not populated yet, only one request to the server will be made and
|
18857
|
-
* the remaining requests will be fulfilled using the response
|
19117
|
+
* the remaining requests will be fulfilled using the response from the first request.
|
18858
19118
|
*
|
18859
19119
|
* A custom default cache built with $cacheFactory can be provided in $http.defaults.cache.
|
18860
19120
|
* To skip it, set configuration property `cache` to `false`.
|
18861
|
-
*
|
19121
|
+
*
|
18862
19122
|
*
|
18863
19123
|
* # Interceptors
|
18864
19124
|
*
|
18865
19125
|
* Before you start creating interceptors, be sure to understand the
|
18866
19126
|
* {@link ng.$q $q and deferred/promise APIs}.
|
18867
19127
|
*
|
18868
|
-
* For purposes of global error handling, authentication or any kind of synchronous or
|
19128
|
+
* For purposes of global error handling, authentication, or any kind of synchronous or
|
18869
19129
|
* asynchronous pre-processing of request or postprocessing of responses, it is desirable to be
|
18870
19130
|
* able to intercept requests before they are handed to the server and
|
18871
|
-
* responses
|
19131
|
+
* responses before they are handed over to the application code that
|
18872
19132
|
* initiated these requests. The interceptors leverage the {@link ng.$q
|
18873
|
-
* promise APIs} to
|
19133
|
+
* promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.
|
18874
19134
|
*
|
18875
|
-
* The interceptors are service factories that are registered with the
|
19135
|
+
* The interceptors are service factories that are registered with the `$httpProvider` by
|
18876
19136
|
* adding them to the `$httpProvider.interceptors` array. The factory is called and
|
18877
19137
|
* injected with dependencies (if specified) and returns the interceptor.
|
18878
19138
|
*
|
@@ -18992,7 +19252,7 @@ function $HttpProvider() {
|
|
18992
19252
|
* When designing web applications, consider security threats from:
|
18993
19253
|
*
|
18994
19254
|
* - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx
|
18995
|
-
* JSON
|
19255
|
+
* JSON vulnerability}
|
18996
19256
|
* - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}
|
18997
19257
|
*
|
18998
19258
|
* Both server and the client must cooperate in order to eliminate these threats. Angular comes
|
@@ -19002,8 +19262,8 @@ function $HttpProvider() {
|
|
19002
19262
|
* ## JSON Vulnerability Protection
|
19003
19263
|
*
|
19004
19264
|
* A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx
|
19005
|
-
* JSON
|
19006
|
-
* {@link http://en.wikipedia.org/wiki/
|
19265
|
+
* JSON vulnerability} allows third party website to turn your JSON resource URL into
|
19266
|
+
* {@link http://en.wikipedia.org/wiki/JSONP JSONP} request under some conditions. To
|
19007
19267
|
* counter this your server can prefix all JSON requests with following string `")]}',\n"`.
|
19008
19268
|
* Angular will automatically strip the prefix before processing it as JSON.
|
19009
19269
|
*
|
@@ -19024,7 +19284,7 @@ function $HttpProvider() {
|
|
19024
19284
|
* ## Cross Site Request Forgery (XSRF) Protection
|
19025
19285
|
*
|
19026
19286
|
* {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which
|
19027
|
-
* an unauthorized site can gain your user's private data. Angular provides
|
19287
|
+
* an unauthorized site can gain your user's private data. Angular provides a mechanism
|
19028
19288
|
* to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
|
19029
19289
|
* (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only
|
19030
19290
|
* JavaScript that runs on your domain could read the cookie, your server can be assured that
|
@@ -19032,12 +19292,12 @@ function $HttpProvider() {
|
|
19032
19292
|
* cross-domain requests.
|
19033
19293
|
*
|
19034
19294
|
* To take advantage of this, your server needs to set a token in a JavaScript readable session
|
19035
|
-
* cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent
|
19295
|
+
* cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
|
19036
19296
|
* server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure
|
19037
|
-
* that only JavaScript running on your domain could have
|
19038
|
-
* unique for each user and must be verifiable by the server (to prevent the JavaScript making
|
19297
|
+
* that only JavaScript running on your domain could have sent the request. The token must be
|
19298
|
+
* unique for each user and must be verifiable by the server (to prevent the JavaScript from making
|
19039
19299
|
* up its own tokens). We recommend that the token is a digest of your site's authentication
|
19040
|
-
* cookie with {@link
|
19300
|
+
* cookie with a {@link https://en.wikipedia.org/wiki/Salt_(cryptography) salt} for added security.
|
19041
19301
|
*
|
19042
19302
|
* The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
|
19043
19303
|
* properties of either $httpProvider.defaults, or the per-request config object.
|
@@ -19064,7 +19324,8 @@ function $HttpProvider() {
|
|
19064
19324
|
* GET request, otherwise if a cache instance built with
|
19065
19325
|
* {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
|
19066
19326
|
* caching.
|
19067
|
-
* - **timeout** – `{number}` – timeout in milliseconds
|
19327
|
+
* - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
|
19328
|
+
* that should abort the request when resolved.
|
19068
19329
|
* - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the
|
19069
19330
|
* XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5
|
19070
19331
|
* requests with credentials} for more information.
|
@@ -19217,7 +19478,7 @@ function $HttpProvider() {
|
|
19217
19478
|
var rejectFn = chain.shift();
|
19218
19479
|
|
19219
19480
|
promise = promise.then(thenFn, rejectFn);
|
19220
|
-
}
|
19481
|
+
}
|
19221
19482
|
|
19222
19483
|
promise.success = function(fn) {
|
19223
19484
|
promise.then(function(response) {
|
@@ -19254,7 +19515,7 @@ function $HttpProvider() {
|
|
19254
19515
|
* @methodOf ng.$http
|
19255
19516
|
*
|
19256
19517
|
* @description
|
19257
|
-
* Shortcut method to perform `GET` request
|
19518
|
+
* Shortcut method to perform `GET` request.
|
19258
19519
|
*
|
19259
19520
|
* @param {string} url Relative or absolute URL specifying the destination of the request
|
19260
19521
|
* @param {Object=} config Optional configuration object
|
@@ -19267,7 +19528,7 @@ function $HttpProvider() {
|
|
19267
19528
|
* @methodOf ng.$http
|
19268
19529
|
*
|
19269
19530
|
* @description
|
19270
|
-
* Shortcut method to perform `DELETE` request
|
19531
|
+
* Shortcut method to perform `DELETE` request.
|
19271
19532
|
*
|
19272
19533
|
* @param {string} url Relative or absolute URL specifying the destination of the request
|
19273
19534
|
* @param {Object=} config Optional configuration object
|
@@ -19280,7 +19541,7 @@ function $HttpProvider() {
|
|
19280
19541
|
* @methodOf ng.$http
|
19281
19542
|
*
|
19282
19543
|
* @description
|
19283
|
-
* Shortcut method to perform `HEAD` request
|
19544
|
+
* Shortcut method to perform `HEAD` request.
|
19284
19545
|
*
|
19285
19546
|
* @param {string} url Relative or absolute URL specifying the destination of the request
|
19286
19547
|
* @param {Object=} config Optional configuration object
|
@@ -19293,7 +19554,7 @@ function $HttpProvider() {
|
|
19293
19554
|
* @methodOf ng.$http
|
19294
19555
|
*
|
19295
19556
|
* @description
|
19296
|
-
* Shortcut method to perform `JSONP` request
|
19557
|
+
* Shortcut method to perform `JSONP` request.
|
19297
19558
|
*
|
19298
19559
|
* @param {string} url Relative or absolute URL specifying the destination of the request.
|
19299
19560
|
* Should contain `JSON_CALLBACK` string.
|
@@ -19308,7 +19569,7 @@ function $HttpProvider() {
|
|
19308
19569
|
* @methodOf ng.$http
|
19309
19570
|
*
|
19310
19571
|
* @description
|
19311
|
-
* Shortcut method to perform `POST` request
|
19572
|
+
* Shortcut method to perform `POST` request.
|
19312
19573
|
*
|
19313
19574
|
* @param {string} url Relative or absolute URL specifying the destination of the request
|
19314
19575
|
* @param {*} data Request content
|
@@ -19322,7 +19583,7 @@ function $HttpProvider() {
|
|
19322
19583
|
* @methodOf ng.$http
|
19323
19584
|
*
|
19324
19585
|
* @description
|
19325
|
-
* Shortcut method to perform `PUT` request
|
19586
|
+
* Shortcut method to perform `PUT` request.
|
19326
19587
|
*
|
19327
19588
|
* @param {string} url Relative or absolute URL specifying the destination of the request
|
19328
19589
|
* @param {*} data Request content
|
@@ -19374,7 +19635,7 @@ function $HttpProvider() {
|
|
19374
19635
|
|
19375
19636
|
|
19376
19637
|
/**
|
19377
|
-
* Makes the request
|
19638
|
+
* Makes the request.
|
19378
19639
|
*
|
19379
19640
|
* !!! ACCESSES CLOSURE VARS:
|
19380
19641
|
* $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
|
@@ -19391,8 +19652,8 @@ function $HttpProvider() {
|
|
19391
19652
|
|
19392
19653
|
|
19393
19654
|
if ((config.cache || defaults.cache) && config.cache !== false && config.method == 'GET') {
|
19394
|
-
cache = isObject(config.cache) ? config.cache
|
19395
|
-
: isObject(defaults.cache) ? defaults.cache
|
19655
|
+
cache = isObject(config.cache) ? config.cache
|
19656
|
+
: isObject(defaults.cache) ? defaults.cache
|
19396
19657
|
: defaultCache;
|
19397
19658
|
}
|
19398
19659
|
|
@@ -19443,7 +19704,7 @@ function $HttpProvider() {
|
|
19443
19704
|
}
|
19444
19705
|
|
19445
19706
|
resolvePromise(response, status, headersString);
|
19446
|
-
$rootScope.$apply();
|
19707
|
+
if (!$rootScope.$$phase) $rootScope.$apply();
|
19447
19708
|
}
|
19448
19709
|
|
19449
19710
|
|
@@ -19527,6 +19788,7 @@ function $HttpBackendProvider() {
|
|
19527
19788
|
function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {
|
19528
19789
|
// TODO(vojta): fix the signature
|
19529
19790
|
return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
|
19791
|
+
var status;
|
19530
19792
|
$browser.$$incOutstandingRequestCount();
|
19531
19793
|
url = url || $browser.url();
|
19532
19794
|
|
@@ -19536,12 +19798,12 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
|
|
19536
19798
|
callbacks[callbackId].data = data;
|
19537
19799
|
};
|
19538
19800
|
|
19539
|
-
jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
|
19801
|
+
var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
|
19540
19802
|
function() {
|
19541
19803
|
if (callbacks[callbackId].data) {
|
19542
19804
|
completeRequest(callback, 200, callbacks[callbackId].data);
|
19543
19805
|
} else {
|
19544
|
-
completeRequest(callback, -2);
|
19806
|
+
completeRequest(callback, status || -2);
|
19545
19807
|
}
|
19546
19808
|
delete callbacks[callbackId];
|
19547
19809
|
});
|
@@ -19552,8 +19814,6 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
|
|
19552
19814
|
if (value) xhr.setRequestHeader(key, value);
|
19553
19815
|
});
|
19554
19816
|
|
19555
|
-
var status;
|
19556
|
-
|
19557
19817
|
// In IE6 and 7, this might be called synchronously when xhr.send below is called and the
|
19558
19818
|
// response is in the cache. the promise api will ensure that to the app code the api is
|
19559
19819
|
// always async
|
@@ -19599,19 +19859,28 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
|
|
19599
19859
|
}
|
19600
19860
|
|
19601
19861
|
xhr.send(post || '');
|
19862
|
+
}
|
19602
19863
|
|
19603
|
-
|
19604
|
-
|
19605
|
-
|
19606
|
-
|
19607
|
-
}, timeout);
|
19608
|
-
}
|
19864
|
+
if (timeout > 0) {
|
19865
|
+
var timeoutId = $browserDefer(timeoutRequest, timeout);
|
19866
|
+
} else if (timeout && timeout.then) {
|
19867
|
+
timeout.then(timeoutRequest);
|
19609
19868
|
}
|
19610
19869
|
|
19611
19870
|
|
19871
|
+
function timeoutRequest() {
|
19872
|
+
status = -1;
|
19873
|
+
jsonpDone && jsonpDone();
|
19874
|
+
xhr && xhr.abort();
|
19875
|
+
}
|
19876
|
+
|
19612
19877
|
function completeRequest(callback, status, response, headersString) {
|
19613
19878
|
// URL_MATCH is defined in src/service/location.js
|
19614
|
-
var protocol = (url.match(
|
19879
|
+
var protocol = (url.match(SERVER_MATCH) || ['', locationProtocol])[1];
|
19880
|
+
|
19881
|
+
// cancel timeout and subsequent timeout promise resolution
|
19882
|
+
timeoutId && $browserDefer.cancel(timeoutId);
|
19883
|
+
jsonpDone = xhr = null;
|
19615
19884
|
|
19616
19885
|
// fix status code for file protocol (it's always 0)
|
19617
19886
|
status = (protocol == 'file') ? (response ? 200 : 404) : status;
|
@@ -19646,6 +19915,7 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
|
|
19646
19915
|
}
|
19647
19916
|
|
19648
19917
|
rawDocument.body.appendChild(script);
|
19918
|
+
return doneWrapper;
|
19649
19919
|
}
|
19650
19920
|
}
|
19651
19921
|
|
@@ -19736,17 +20006,17 @@ function $TimeoutProvider() {
|
|
19736
20006
|
* block and delegates any exceptions to
|
19737
20007
|
* {@link ng.$exceptionHandler $exceptionHandler} service.
|
19738
20008
|
*
|
19739
|
-
* The return value of registering a timeout function is a promise which will be resolved when
|
20009
|
+
* The return value of registering a timeout function is a promise, which will be resolved when
|
19740
20010
|
* the timeout is reached and the timeout function is executed.
|
19741
20011
|
*
|
19742
|
-
* To cancel a
|
20012
|
+
* To cancel a timeout request, call `$timeout.cancel(promise)`.
|
19743
20013
|
*
|
19744
20014
|
* In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to
|
19745
20015
|
* synchronously flush the queue of deferred functions.
|
19746
20016
|
*
|
19747
|
-
* @param {function()} fn A function,
|
20017
|
+
* @param {function()} fn A function, whose execution should be delayed.
|
19748
20018
|
* @param {number=} [delay=0] Delay in milliseconds.
|
19749
|
-
* @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise
|
20019
|
+
* @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
|
19750
20020
|
* will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
|
19751
20021
|
* @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
|
19752
20022
|
* promise will be resolved with is the return value of the `fn` function.
|
@@ -19786,7 +20056,7 @@ function $TimeoutProvider() {
|
|
19786
20056
|
* @methodOf ng.$timeout
|
19787
20057
|
*
|
19788
20058
|
* @description
|
19789
|
-
* Cancels a task associated with the `promise`. As a result of this the promise will be
|
20059
|
+
* Cancels a task associated with the `promise`. As a result of this, the promise will be
|
19790
20060
|
* resolved with a rejection.
|
19791
20061
|
*
|
19792
20062
|
* @param {Promise=} promise Promise returned by the `$timeout` function.
|
@@ -19874,7 +20144,7 @@ function $TimeoutProvider() {
|
|
19874
20144
|
*
|
19875
20145
|
* The general syntax in templates is as follows:
|
19876
20146
|
*
|
19877
|
-
* {{ expression | [
|
20147
|
+
* {{ expression [| filter_name[:parameter_value] ... ] }}
|
19878
20148
|
*
|
19879
20149
|
* @param {String} name Name of the filter function to retrieve
|
19880
20150
|
* @return {Function} the filter function
|
@@ -19976,7 +20246,7 @@ function $FilterProvider($provide) {
|
|
19976
20246
|
<hr>
|
19977
20247
|
Any: <input ng-model="search.$"> <br>
|
19978
20248
|
Name only <input ng-model="search.name"><br>
|
19979
|
-
Phone only <input ng-model="search.phone"
|
20249
|
+
Phone only <input ng-model="search.phone"><br>
|
19980
20250
|
Equality <input type="checkbox" ng-model="strict"><br>
|
19981
20251
|
<table id="searchObjResults">
|
19982
20252
|
<tr><th>Name</th><th>Phone</th></tr>
|
@@ -20308,6 +20578,7 @@ function padNumber(num, digits, trim) {
|
|
20308
20578
|
|
20309
20579
|
|
20310
20580
|
function dateGetter(name, size, offset, trim) {
|
20581
|
+
offset = offset || 0;
|
20311
20582
|
return function(date) {
|
20312
20583
|
var value = date['get' + name]();
|
20313
20584
|
if (offset > 0 || value > -offset)
|
@@ -20422,7 +20693,7 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
|
|
20422
20693
|
* (e.g. `"h o''clock"`).
|
20423
20694
|
*
|
20424
20695
|
* @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
|
20425
|
-
* number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and
|
20696
|
+
* number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and its
|
20426
20697
|
* shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
|
20427
20698
|
* specified in the string input, the time is considered to be in the local timezone.
|
20428
20699
|
* @param {string=} format Formatting rules (see Description). If not specified,
|
@@ -20471,7 +20742,11 @@ function dateFilter($locale) {
|
|
20471
20742
|
tzMin = int(match[9] + match[11]);
|
20472
20743
|
}
|
20473
20744
|
dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));
|
20474
|
-
|
20745
|
+
var h = int(match[4]||0) - tzHour;
|
20746
|
+
var m = int(match[5]||0) - tzMin
|
20747
|
+
var s = int(match[6]||0);
|
20748
|
+
var ms = Math.round(parseFloat('0.' + (match[7]||0)) * 1000);
|
20749
|
+
timeSetter.call(date, h, m, s, ms);
|
20475
20750
|
return date;
|
20476
20751
|
}
|
20477
20752
|
return string;
|
@@ -20953,27 +21228,52 @@ var htmlAnchorDirective = valueFn({
|
|
20953
21228
|
|
20954
21229
|
/**
|
20955
21230
|
* @ngdoc directive
|
20956
|
-
* @name ng.directive:ngSrc
|
21231
|
+
* @name ng.directive:ngSrc
|
21232
|
+
* @restrict A
|
21233
|
+
*
|
21234
|
+
* @description
|
21235
|
+
* Using Angular markup like `{{hash}}` in a `src` attribute doesn't
|
21236
|
+
* work right: The browser will fetch from the URL with the literal
|
21237
|
+
* text `{{hash}}` until Angular replaces the expression inside
|
21238
|
+
* `{{hash}}`. The `ngSrc` directive solves this problem.
|
21239
|
+
*
|
21240
|
+
* The buggy way to write it:
|
21241
|
+
* <pre>
|
21242
|
+
* <img src="http://www.gravatar.com/avatar/{{hash}}"/>
|
21243
|
+
* </pre>
|
21244
|
+
*
|
21245
|
+
* The correct way to write it:
|
21246
|
+
* <pre>
|
21247
|
+
* <img ng-src="http://www.gravatar.com/avatar/{{hash}}"/>
|
21248
|
+
* </pre>
|
21249
|
+
*
|
21250
|
+
* @element IMG
|
21251
|
+
* @param {template} ngSrc any string which can contain `{{}}` markup.
|
21252
|
+
*/
|
21253
|
+
|
21254
|
+
/**
|
21255
|
+
* @ngdoc directive
|
21256
|
+
* @name ng.directive:ngSrcset
|
20957
21257
|
* @restrict A
|
20958
21258
|
*
|
20959
21259
|
* @description
|
20960
|
-
* Using Angular markup like `{{hash}}` in a `
|
21260
|
+
* Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't
|
20961
21261
|
* work right: The browser will fetch from the URL with the literal
|
20962
21262
|
* text `{{hash}}` until Angular replaces the expression inside
|
20963
|
-
* `{{hash}}`. The `
|
21263
|
+
* `{{hash}}`. The `ngSrcset` directive solves this problem.
|
20964
21264
|
*
|
20965
21265
|
* The buggy way to write it:
|
20966
21266
|
* <pre>
|
20967
|
-
* <img
|
21267
|
+
* <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/>
|
20968
21268
|
* </pre>
|
20969
21269
|
*
|
20970
21270
|
* The correct way to write it:
|
20971
21271
|
* <pre>
|
20972
|
-
* <img ng-
|
21272
|
+
* <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/>
|
20973
21273
|
* </pre>
|
20974
21274
|
*
|
20975
21275
|
* @element IMG
|
20976
|
-
* @param {template}
|
21276
|
+
* @param {template} ngSrcset any string which can contain `{{}}` markup.
|
20977
21277
|
*/
|
20978
21278
|
|
20979
21279
|
/**
|
@@ -21196,8 +21496,8 @@ forEach(BOOLEAN_ATTR, function(propName, attrName) {
|
|
21196
21496
|
});
|
21197
21497
|
|
21198
21498
|
|
21199
|
-
// ng-src, ng-href are interpolated
|
21200
|
-
forEach(['src', 'href'], function(attrName) {
|
21499
|
+
// ng-src, ng-srcset, ng-href are interpolated
|
21500
|
+
forEach(['src', 'srcset', 'href'], function(attrName) {
|
21201
21501
|
var normalized = directiveNormalize('ng-' + attrName);
|
21202
21502
|
ngAttributeAliasDirectives[normalized] = function() {
|
21203
21503
|
return {
|
@@ -21629,8 +21929,8 @@ var inputType = {
|
|
21629
21929
|
*
|
21630
21930
|
* @param {string} ngModel Assignable angular expression to data-bind to.
|
21631
21931
|
* @param {string=} name Property name of the form under which the control is published.
|
21632
|
-
* @param {string=} min Sets the `min` validation error key if the value entered is less
|
21633
|
-
* @param {string=} max Sets the `max` validation error key if the value entered is greater
|
21932
|
+
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
|
21933
|
+
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
|
21634
21934
|
* @param {string=} required Sets `required` validation error key if the value is not entered.
|
21635
21935
|
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
|
21636
21936
|
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
|
@@ -21949,6 +22249,15 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
|
|
21949
22249
|
} else {
|
21950
22250
|
var timeout;
|
21951
22251
|
|
22252
|
+
var deferListener = function() {
|
22253
|
+
if (!timeout) {
|
22254
|
+
timeout = $browser.defer(function() {
|
22255
|
+
listener();
|
22256
|
+
timeout = null;
|
22257
|
+
});
|
22258
|
+
}
|
22259
|
+
};
|
22260
|
+
|
21952
22261
|
element.bind('keydown', function(event) {
|
21953
22262
|
var key = event.keyCode;
|
21954
22263
|
|
@@ -21956,16 +22265,16 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
|
|
21956
22265
|
// command modifiers arrows
|
21957
22266
|
if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
|
21958
22267
|
|
21959
|
-
|
21960
|
-
timeout = $browser.defer(function() {
|
21961
|
-
listener();
|
21962
|
-
timeout = null;
|
21963
|
-
});
|
21964
|
-
}
|
22268
|
+
deferListener();
|
21965
22269
|
});
|
21966
22270
|
|
21967
22271
|
// if user paste into input using mouse, we need "change" event to catch it
|
21968
22272
|
element.bind('change', listener);
|
22273
|
+
|
22274
|
+
// if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
|
22275
|
+
if ($sniffer.hasEvent('paste')) {
|
22276
|
+
element.bind('paste cut', deferListener);
|
22277
|
+
}
|
21969
22278
|
}
|
21970
22279
|
|
21971
22280
|
|
@@ -21975,7 +22284,8 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
|
|
21975
22284
|
|
21976
22285
|
// pattern validator
|
21977
22286
|
var pattern = attr.ngPattern,
|
21978
|
-
patternValidator
|
22287
|
+
patternValidator,
|
22288
|
+
match;
|
21979
22289
|
|
21980
22290
|
var validate = function(regexp, value) {
|
21981
22291
|
if (isEmpty(value) || regexp.test(value)) {
|
@@ -21988,8 +22298,9 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
|
|
21988
22298
|
};
|
21989
22299
|
|
21990
22300
|
if (pattern) {
|
21991
|
-
|
21992
|
-
|
22301
|
+
match = pattern.match(/^\/(.*)\/([gim]*)$/);
|
22302
|
+
if (match) {
|
22303
|
+
pattern = new RegExp(match[1], match[2]);
|
21993
22304
|
patternValidator = function(value) {
|
21994
22305
|
return validate(pattern, value)
|
21995
22306
|
};
|
@@ -22264,7 +22575,7 @@ function checkboxInputType(scope, element, attr, ctrl) {
|
|
22264
22575
|
<tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>
|
22265
22576
|
<tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>
|
22266
22577
|
<tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>
|
22267
|
-
<tt>myForm.
|
22578
|
+
<tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br>
|
22268
22579
|
<tt>myForm.$valid = {{myForm.$valid}}</tt><br>
|
22269
22580
|
<tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
|
22270
22581
|
<tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>
|
@@ -22543,7 +22854,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
22543
22854
|
* For example {@link ng.directive:input input} or
|
22544
22855
|
* {@link ng.directive:select select} directives call it.
|
22545
22856
|
*
|
22546
|
-
* It internally calls all `
|
22857
|
+
* It internally calls all `parsers` and if resulted value is valid, updates the model and
|
22547
22858
|
* calls all registered change listeners.
|
22548
22859
|
*
|
22549
22860
|
* @param {string} value Value from the view.
|
@@ -22849,7 +23160,7 @@ var ngValueDirective = function() {
|
|
22849
23160
|
* Typically, you don't use `ngBind` directly, but instead you use the double curly markup like
|
22850
23161
|
* `{{ expression }}` which is similar but less verbose.
|
22851
23162
|
*
|
22852
|
-
*
|
23163
|
+
* One scenario in which the use of `ngBind` is preferred over `{{ expression }}` binding is when
|
22853
23164
|
* it's desirable to put bindings into template that is momentarily displayed by the browser in its
|
22854
23165
|
* raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the
|
22855
23166
|
* bindings invisible to the user while the page is loading.
|
@@ -22990,9 +23301,9 @@ function classDirective(name, selector) {
|
|
22990
23301
|
|
22991
23302
|
if (name !== 'ngClass') {
|
22992
23303
|
scope.$watch('$index', function($index, old$index) {
|
22993
|
-
var mod = $index
|
22994
|
-
if (mod !== old$index
|
22995
|
-
if (mod
|
23304
|
+
var mod = $index & 1;
|
23305
|
+
if (mod !== old$index & 1) {
|
23306
|
+
if (mod === selector) {
|
22996
23307
|
addClass(scope.$eval(attr[name]));
|
22997
23308
|
} else {
|
22998
23309
|
removeClass(scope.$eval(attr[name]));
|
@@ -23004,12 +23315,12 @@ function classDirective(name, selector) {
|
|
23004
23315
|
|
23005
23316
|
function ngClassWatchAction(newVal) {
|
23006
23317
|
if (selector === true || scope.$index % 2 === selector) {
|
23007
|
-
if (oldVal && (newVal
|
23318
|
+
if (oldVal && !equals(newVal,oldVal)) {
|
23008
23319
|
removeClass(oldVal);
|
23009
23320
|
}
|
23010
23321
|
addClass(newVal);
|
23011
23322
|
}
|
23012
|
-
oldVal = newVal;
|
23323
|
+
oldVal = copy(newVal);
|
23013
23324
|
}
|
23014
23325
|
|
23015
23326
|
|
@@ -23135,7 +23446,7 @@ var ngClassOddDirective = classDirective('Odd', 0);
|
|
23135
23446
|
* @name ng.directive:ngClassEven
|
23136
23447
|
*
|
23137
23448
|
* @description
|
23138
|
-
* The `ngClassOdd` and `ngClassEven`
|
23449
|
+
* The `ngClassOdd` and `ngClassEven` directives work exactly as
|
23139
23450
|
* {@link ng.directive:ngClass ngClass}, except it works in
|
23140
23451
|
* conjunction with `ngRepeat` and takes affect only on odd (even) rows.
|
23141
23452
|
*
|
@@ -23252,14 +23563,14 @@ var ngCloakDirective = ngDirective({
|
|
23252
23563
|
* * Controller — The `ngController` directive specifies a Controller class; the class has
|
23253
23564
|
* methods that typically express the business logic behind the application.
|
23254
23565
|
*
|
23255
|
-
* Note that an alternative way to define controllers is via the
|
23256
|
-
* service.
|
23566
|
+
* Note that an alternative way to define controllers is via the {@link ng.$route $route} service.
|
23257
23567
|
*
|
23258
23568
|
* @element ANY
|
23259
23569
|
* @scope
|
23260
23570
|
* @param {expression} ngController Name of a globally accessible constructor function or an
|
23261
23571
|
* {@link guide/expression expression} that on the current scope evaluates to a
|
23262
|
-
* constructor function.
|
23572
|
+
* constructor function. The controller instance can further be published into the scope
|
23573
|
+
* by adding `as localName` the controller name attribute.
|
23263
23574
|
*
|
23264
23575
|
* @example
|
23265
23576
|
* Here is a simple form for editing user contact information. Adding, removing, clearing, and
|
@@ -23267,8 +23578,75 @@ var ngCloakDirective = ngDirective({
|
|
23267
23578
|
* easily be called from the angular markup. Notice that the scope becomes the `this` for the
|
23268
23579
|
* controller's instance. This allows for easy access to the view data from the controller. Also
|
23269
23580
|
* notice that any changes to the data are automatically reflected in the View without the need
|
23270
|
-
* for a manual update.
|
23581
|
+
* for a manual update. The example is included in two different declaration styles based on
|
23582
|
+
* your style preferences.
|
23271
23583
|
<doc:example>
|
23584
|
+
<doc:source>
|
23585
|
+
<script>
|
23586
|
+
function SettingsController() {
|
23587
|
+
this.name = "John Smith";
|
23588
|
+
this.contacts = [
|
23589
|
+
{type: 'phone', value: '408 555 1212'},
|
23590
|
+
{type: 'email', value: 'john.smith@example.org'} ];
|
23591
|
+
};
|
23592
|
+
|
23593
|
+
SettingsController.prototype.greet = function() {
|
23594
|
+
alert(this.name);
|
23595
|
+
};
|
23596
|
+
|
23597
|
+
SettingsController.prototype.addContact = function() {
|
23598
|
+
this.contacts.push({type: 'email', value: 'yourname@example.org'});
|
23599
|
+
};
|
23600
|
+
|
23601
|
+
SettingsController.prototype.removeContact = function(contactToRemove) {
|
23602
|
+
var index = this.contacts.indexOf(contactToRemove);
|
23603
|
+
this.contacts.splice(index, 1);
|
23604
|
+
};
|
23605
|
+
|
23606
|
+
SettingsController.prototype.clearContact = function(contact) {
|
23607
|
+
contact.type = 'phone';
|
23608
|
+
contact.value = '';
|
23609
|
+
};
|
23610
|
+
</script>
|
23611
|
+
<div ng-controller="SettingsController as settings">
|
23612
|
+
Name: <input type="text" ng-model="settings.name"/>
|
23613
|
+
[ <a href="" ng-click="settings.greet()">greet</a> ]<br/>
|
23614
|
+
Contact:
|
23615
|
+
<ul>
|
23616
|
+
<li ng-repeat="contact in settings.contacts">
|
23617
|
+
<select ng-model="contact.type">
|
23618
|
+
<option>phone</option>
|
23619
|
+
<option>email</option>
|
23620
|
+
</select>
|
23621
|
+
<input type="text" ng-model="contact.value"/>
|
23622
|
+
[ <a href="" ng-click="settings.clearContact(contact)">clear</a>
|
23623
|
+
| <a href="" ng-click="settings.removeContact(contact)">X</a> ]
|
23624
|
+
</li>
|
23625
|
+
<li>[ <a href="" ng-click="settings.addContact()">add</a> ]</li>
|
23626
|
+
</ul>
|
23627
|
+
</div>
|
23628
|
+
</doc:source>
|
23629
|
+
<doc:scenario>
|
23630
|
+
it('should check controller', function() {
|
23631
|
+
expect(element('.doc-example-live div>:input').val()).toBe('John Smith');
|
23632
|
+
expect(element('.doc-example-live li:nth-child(1) input').val())
|
23633
|
+
.toBe('408 555 1212');
|
23634
|
+
expect(element('.doc-example-live li:nth-child(2) input').val())
|
23635
|
+
.toBe('john.smith@example.org');
|
23636
|
+
|
23637
|
+
element('.doc-example-live li:first a:contains("clear")').click();
|
23638
|
+
expect(element('.doc-example-live li:first input').val()).toBe('');
|
23639
|
+
|
23640
|
+
element('.doc-example-live li:last a:contains("add")').click();
|
23641
|
+
expect(element('.doc-example-live li:nth-child(3) input').val())
|
23642
|
+
.toBe('yourname@example.org');
|
23643
|
+
});
|
23644
|
+
</doc:scenario>
|
23645
|
+
</doc:example>
|
23646
|
+
|
23647
|
+
|
23648
|
+
|
23649
|
+
<doc:example>
|
23272
23650
|
<doc:source>
|
23273
23651
|
<script>
|
23274
23652
|
function SettingsController($scope) {
|
@@ -23331,6 +23709,7 @@ var ngCloakDirective = ngDirective({
|
|
23331
23709
|
});
|
23332
23710
|
</doc:scenario>
|
23333
23711
|
</doc:example>
|
23712
|
+
|
23334
23713
|
*/
|
23335
23714
|
var ngControllerDirective = [function() {
|
23336
23715
|
return {
|
@@ -23344,16 +23723,32 @@ var ngControllerDirective = [function() {
|
|
23344
23723
|
* @name ng.directive:ngCsp
|
23345
23724
|
* @priority 1000
|
23346
23725
|
*
|
23726
|
+
* @element html
|
23347
23727
|
* @description
|
23348
23728
|
* Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
|
23349
|
-
*
|
23350
|
-
*
|
23351
|
-
*
|
23352
|
-
*
|
23353
|
-
*
|
23354
|
-
*
|
23355
|
-
*
|
23356
|
-
*
|
23729
|
+
*
|
23730
|
+
* This is necessary when developing things like Google Chrome Extensions.
|
23731
|
+
*
|
23732
|
+
* CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).
|
23733
|
+
* For us to be compatible, we just need to implement the "getterFn" in $parse without violating
|
23734
|
+
* any of these restrictions.
|
23735
|
+
*
|
23736
|
+
* AngularJS uses `Function(string)` generated functions as a speed optimization. By applying `ngCsp`
|
23737
|
+
* it is be possible to opt into the CSP compatible mode. When this mode is on AngularJS will
|
23738
|
+
* evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will
|
23739
|
+
* be raised.
|
23740
|
+
*
|
23741
|
+
* In order to use this feature put `ngCsp` directive on the root element of the application.
|
23742
|
+
*
|
23743
|
+
* @example
|
23744
|
+
* This example shows how to apply the `ngCsp` directive to the `html` tag.
|
23745
|
+
<pre>
|
23746
|
+
<!doctype html>
|
23747
|
+
<html ng-app ng-csp>
|
23748
|
+
...
|
23749
|
+
...
|
23750
|
+
</html>
|
23751
|
+
</pre>
|
23357
23752
|
*/
|
23358
23753
|
|
23359
23754
|
var ngCspDirective = ['$sniffer', function($sniffer) {
|
@@ -23634,6 +24029,114 @@ var ngSubmitDirective = ngDirective(function(scope, element, attrs) {
|
|
23634
24029
|
});
|
23635
24030
|
});
|
23636
24031
|
|
24032
|
+
/**
|
24033
|
+
* @ngdoc directive
|
24034
|
+
* @name ng.directive:ngIf
|
24035
|
+
* @restrict A
|
24036
|
+
*
|
24037
|
+
* @description
|
24038
|
+
* The `ngIf` directive removes and recreates a portion of the DOM tree (HTML)
|
24039
|
+
* conditionally based on **"falsy"** and **"truthy"** values, respectively, evaluated within
|
24040
|
+
* an {expression}. In other words, if the expression assigned to **ngIf evaluates to a false
|
24041
|
+
* value** then **the element is removed from the DOM** and **if true** then **a clone of the
|
24042
|
+
* element is reinserted into the DOM**.
|
24043
|
+
*
|
24044
|
+
* `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the
|
24045
|
+
* element in the DOM rather than changing its visibility via the `display` css property. A common
|
24046
|
+
* case when this difference is significant is when using css selectors that rely on an element's
|
24047
|
+
* position within the DOM (HTML), such as the `:first-child` or `:last-child` pseudo-classes.
|
24048
|
+
*
|
24049
|
+
* Note that **when an element is removed using ngIf its scope is destroyed** and **a new scope
|
24050
|
+
* is created when the element is restored**. The scope created within `ngIf` inherits from
|
24051
|
+
* its parent scope using
|
24052
|
+
* {@link https://github.com/angular/angular.js/wiki/The-Nuances-of-Scope-Prototypal-Inheritance prototypal inheritance}.
|
24053
|
+
* An important implication of this is if `ngModel` is used within `ngIf` to bind to
|
24054
|
+
* a javascript primitive defined in the parent scope. In this case any modifications made to the
|
24055
|
+
* variable within the child scope will override (hide) the value in the parent scope.
|
24056
|
+
*
|
24057
|
+
* Also, `ngIf` recreates elements using their compiled state. An example scenario of this behavior
|
24058
|
+
* is if an element's class attribute is directly modified after it's compiled, using something like
|
24059
|
+
* jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element
|
24060
|
+
* the added class will be lost because the original compiled state is used to regenerate the element.
|
24061
|
+
*
|
24062
|
+
* Additionally, you can provide animations via the ngAnimate attribute to animate the **enter**
|
24063
|
+
* and **leave** effects.
|
24064
|
+
*
|
24065
|
+
* @animations
|
24066
|
+
* enter - happens just after the ngIf contents change and a new DOM element is created and injected into the ngIf container
|
24067
|
+
* leave - happens just before the ngIf contents are removed from the DOM
|
24068
|
+
*
|
24069
|
+
* @element ANY
|
24070
|
+
* @scope
|
24071
|
+
* @param {expression} ngIf If the {@link guide/expression expression} is falsy then
|
24072
|
+
* the element is removed from the DOM tree (HTML).
|
24073
|
+
*
|
24074
|
+
* @example
|
24075
|
+
<example animations="true">
|
24076
|
+
<file name="index.html">
|
24077
|
+
Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /><br/>
|
24078
|
+
Show when checked:
|
24079
|
+
<span ng-if="checked" ng-animate="'example'">
|
24080
|
+
I'm removed when the checkbox is unchecked.
|
24081
|
+
</span>
|
24082
|
+
</file>
|
24083
|
+
<file name="animations.css">
|
24084
|
+
.example-leave, .example-enter {
|
24085
|
+
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
24086
|
+
-moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
24087
|
+
-ms-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
24088
|
+
-o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
24089
|
+
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
24090
|
+
}
|
24091
|
+
|
24092
|
+
.example-enter {
|
24093
|
+
opacity:0;
|
24094
|
+
}
|
24095
|
+
.example-enter.example-enter-active {
|
24096
|
+
opacity:1;
|
24097
|
+
}
|
24098
|
+
|
24099
|
+
.example-leave {
|
24100
|
+
opacity:1;
|
24101
|
+
}
|
24102
|
+
.example-leave.example-leave-active {
|
24103
|
+
opacity:0;
|
24104
|
+
}
|
24105
|
+
</file>
|
24106
|
+
</example>
|
24107
|
+
*/
|
24108
|
+
var ngIfDirective = ['$animator', function($animator) {
|
24109
|
+
return {
|
24110
|
+
transclude: 'element',
|
24111
|
+
priority: 1000,
|
24112
|
+
terminal: true,
|
24113
|
+
restrict: 'A',
|
24114
|
+
compile: function (element, attr, transclude) {
|
24115
|
+
return function ($scope, $element, $attr) {
|
24116
|
+
var animate = $animator($scope, $attr);
|
24117
|
+
var childElement, childScope;
|
24118
|
+
$scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
|
24119
|
+
if (childElement) {
|
24120
|
+
animate.leave(childElement);
|
24121
|
+
childElement = undefined;
|
24122
|
+
}
|
24123
|
+
if (childScope) {
|
24124
|
+
childScope.$destroy();
|
24125
|
+
childScope = undefined;
|
24126
|
+
}
|
24127
|
+
if (toBoolean(value)) {
|
24128
|
+
childScope = $scope.$new();
|
24129
|
+
transclude(childScope, function (clone) {
|
24130
|
+
childElement = clone;
|
24131
|
+
animate.enter(clone, $element.parent(), $element);
|
24132
|
+
});
|
24133
|
+
}
|
24134
|
+
});
|
24135
|
+
}
|
24136
|
+
}
|
24137
|
+
}
|
24138
|
+
}];
|
24139
|
+
|
23637
24140
|
/**
|
23638
24141
|
* @ngdoc directive
|
23639
24142
|
* @name ng.directive:ngInclude
|
@@ -23667,7 +24170,7 @@ var ngSubmitDirective = ngDirective(function(scope, element, attrs) {
|
|
23667
24170
|
* - Otherwise enable scrolling only if the expression evaluates to truthy value.
|
23668
24171
|
*
|
23669
24172
|
* @example
|
23670
|
-
<example>
|
24173
|
+
<example animations="true">
|
23671
24174
|
<file name="index.html">
|
23672
24175
|
<div ng-controller="Ctrl">
|
23673
24176
|
<select ng-model="template" ng-options="t.name for t in templates">
|
@@ -23695,8 +24198,8 @@ var ngSubmitDirective = ngDirective(function(scope, element, attrs) {
|
|
23695
24198
|
<div>Content of template2.html</div>
|
23696
24199
|
</file>
|
23697
24200
|
<file name="animations.css">
|
23698
|
-
.example-leave
|
23699
|
-
.example-enter
|
24201
|
+
.example-leave,
|
24202
|
+
.example-enter {
|
23700
24203
|
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
23701
24204
|
-moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
23702
24205
|
-ms-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
@@ -23715,17 +24218,17 @@ var ngSubmitDirective = ngDirective(function(scope, element, attrs) {
|
|
23715
24218
|
padding:10px;
|
23716
24219
|
}
|
23717
24220
|
|
23718
|
-
.example-enter
|
24221
|
+
.example-enter {
|
23719
24222
|
top:-50px;
|
23720
24223
|
}
|
23721
|
-
.example-enter
|
24224
|
+
.example-enter.example-enter-active {
|
23722
24225
|
top:0;
|
23723
24226
|
}
|
23724
24227
|
|
23725
|
-
.example-leave
|
24228
|
+
.example-leave {
|
23726
24229
|
top:0;
|
23727
24230
|
}
|
23728
|
-
.example-leave
|
24231
|
+
.example-leave.example-leave-active {
|
23729
24232
|
top:50px;
|
23730
24233
|
}
|
23731
24234
|
</file>
|
@@ -23748,6 +24251,16 @@ var ngSubmitDirective = ngDirective(function(scope, element, attrs) {
|
|
23748
24251
|
*/
|
23749
24252
|
|
23750
24253
|
|
24254
|
+
/**
|
24255
|
+
* @ngdoc event
|
24256
|
+
* @name ng.directive:ngInclude#$includeContentRequested
|
24257
|
+
* @eventOf ng.directive:ngInclude
|
24258
|
+
* @eventType emit on the scope ngInclude was declared in
|
24259
|
+
* @description
|
24260
|
+
* Emitted every time the ngInclude content is requested.
|
24261
|
+
*/
|
24262
|
+
|
24263
|
+
|
23751
24264
|
/**
|
23752
24265
|
* @ngdoc event
|
23753
24266
|
* @name ng.directive:ngInclude#$includeContentLoaded
|
@@ -23804,6 +24317,7 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
|
|
23804
24317
|
}).error(function() {
|
23805
24318
|
if (thisChangeId === changeCounter) clearContent();
|
23806
24319
|
});
|
24320
|
+
scope.$emit('$includeContentRequested');
|
23807
24321
|
} else {
|
23808
24322
|
clearContent();
|
23809
24323
|
}
|
@@ -24075,7 +24589,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp
|
|
24075
24589
|
if (!isNaN(value)) {
|
24076
24590
|
//if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,
|
24077
24591
|
//check it against pluralization rules in $locale service
|
24078
|
-
if (!whens
|
24592
|
+
if (!(value in whens)) value = $locale.pluralCat(value - offset);
|
24079
24593
|
return whensExpFns[value](scope, element, true);
|
24080
24594
|
} else {
|
24081
24595
|
return '';
|
@@ -24175,9 +24689,9 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp
|
|
24175
24689
|
</div>
|
24176
24690
|
</file>
|
24177
24691
|
<file name="animations.css">
|
24178
|
-
.example-repeat-enter
|
24179
|
-
.example-repeat-leave
|
24180
|
-
.example-repeat-move
|
24692
|
+
.example-repeat-enter,
|
24693
|
+
.example-repeat-leave,
|
24694
|
+
.example-repeat-move {
|
24181
24695
|
-webkit-transition:all linear 0.5s;
|
24182
24696
|
-moz-transition:all linear 0.5s;
|
24183
24697
|
-ms-transition:all linear 0.5s;
|
@@ -24185,26 +24699,26 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp
|
|
24185
24699
|
transition:all linear 0.5s;
|
24186
24700
|
}
|
24187
24701
|
|
24188
|
-
.example-repeat-enter
|
24702
|
+
.example-repeat-enter {
|
24189
24703
|
line-height:0;
|
24190
24704
|
opacity:0;
|
24191
24705
|
}
|
24192
|
-
.example-repeat-enter
|
24706
|
+
.example-repeat-enter.example-repeat-enter-active {
|
24193
24707
|
line-height:20px;
|
24194
24708
|
opacity:1;
|
24195
24709
|
}
|
24196
24710
|
|
24197
|
-
.example-repeat-leave
|
24711
|
+
.example-repeat-leave {
|
24198
24712
|
opacity:1;
|
24199
24713
|
line-height:20px;
|
24200
24714
|
}
|
24201
|
-
.example-repeat-leave
|
24715
|
+
.example-repeat-leave.example-repeat-leave-active {
|
24202
24716
|
opacity:0;
|
24203
24717
|
line-height:0;
|
24204
24718
|
}
|
24205
24719
|
|
24206
|
-
.example-repeat-move
|
24207
|
-
.example-repeat-move
|
24720
|
+
.example-repeat-move { }
|
24721
|
+
.example-repeat-move.example-repeat-move-active { }
|
24208
24722
|
</file>
|
24209
24723
|
<file name="scenario.js">
|
24210
24724
|
it('should render initial data set', function() {
|
@@ -24240,7 +24754,7 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {
|
|
24240
24754
|
var animate = $animator($scope, $attr);
|
24241
24755
|
var expression = $attr.ngRepeat;
|
24242
24756
|
var match = expression.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/),
|
24243
|
-
trackByExp,
|
24757
|
+
trackByExp, trackByExpGetter, trackByIdFn, lhs, rhs, valueIdentifier, keyIdentifier,
|
24244
24758
|
hashFnLocals = {$id: hashKey};
|
24245
24759
|
|
24246
24760
|
if (!match) {
|
@@ -24253,13 +24767,13 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {
|
|
24253
24767
|
trackByExp = match[4];
|
24254
24768
|
|
24255
24769
|
if (trackByExp) {
|
24256
|
-
|
24770
|
+
trackByExpGetter = $parse(trackByExp);
|
24257
24771
|
trackByIdFn = function(key, value, index) {
|
24258
24772
|
// assign key, value, and $index to the locals so that they can be used in hash functions
|
24259
24773
|
if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
|
24260
24774
|
hashFnLocals[valueIdentifier] = value;
|
24261
24775
|
hashFnLocals.$index = index;
|
24262
|
-
return
|
24776
|
+
return trackByExpGetter($scope, hashFnLocals);
|
24263
24777
|
};
|
24264
24778
|
} else {
|
24265
24779
|
trackByIdFn = function(key, value) {
|
@@ -24299,7 +24813,7 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {
|
|
24299
24813
|
nextBlockOrder = [];
|
24300
24814
|
|
24301
24815
|
|
24302
|
-
if (
|
24816
|
+
if (isArrayLike(collection)) {
|
24303
24817
|
collectionKeys = collection;
|
24304
24818
|
} else {
|
24305
24819
|
// if object, extract keys, sort them and use to determine order of iteration over obj props
|
@@ -24320,7 +24834,8 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {
|
|
24320
24834
|
key = (collection === collectionKeys) ? index : collectionKeys[index];
|
24321
24835
|
value = collection[key];
|
24322
24836
|
trackById = trackByIdFn(key, value, index);
|
24323
|
-
if((
|
24837
|
+
if(lastBlockMap.hasOwnProperty(trackById)) {
|
24838
|
+
block = lastBlockMap[trackById]
|
24324
24839
|
delete lastBlockMap[trackById];
|
24325
24840
|
nextBlockMap[trackById] = block;
|
24326
24841
|
nextBlockOrder[index] = block;
|
@@ -24330,10 +24845,12 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {
|
|
24330
24845
|
if (block && block.element) lastBlockMap[block.id] = block;
|
24331
24846
|
});
|
24332
24847
|
// This is a duplicate and we need to throw an error
|
24333
|
-
throw new Error('Duplicates in a repeater are not allowed. Repeater: ' + expression
|
24848
|
+
throw new Error('Duplicates in a repeater are not allowed. Repeater: ' + expression +
|
24849
|
+
' key: ' + trackById);
|
24334
24850
|
} else {
|
24335
24851
|
// new never before seen block
|
24336
24852
|
nextBlockOrder[index] = { id: trackById };
|
24853
|
+
nextBlockMap[trackById] = false;
|
24337
24854
|
}
|
24338
24855
|
}
|
24339
24856
|
|
@@ -24445,7 +24962,7 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {
|
|
24445
24962
|
</div>
|
24446
24963
|
</file>
|
24447
24964
|
<file name="animations.css">
|
24448
|
-
.example-show
|
24965
|
+
.example-show, .example-hide {
|
24449
24966
|
-webkit-transition:all linear 0.5s;
|
24450
24967
|
-moz-transition:all linear 0.5s;
|
24451
24968
|
-ms-transition:all linear 0.5s;
|
@@ -24453,12 +24970,12 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {
|
|
24453
24970
|
transition:all linear 0.5s;
|
24454
24971
|
}
|
24455
24972
|
|
24456
|
-
.example-show
|
24973
|
+
.example-show {
|
24457
24974
|
line-height:0;
|
24458
24975
|
opacity:0;
|
24459
24976
|
padding:0 10px;
|
24460
24977
|
}
|
24461
|
-
.example-show-
|
24978
|
+
.example-show-active.example-show-active {
|
24462
24979
|
line-height:20px;
|
24463
24980
|
opacity:1;
|
24464
24981
|
padding:10px;
|
@@ -24466,14 +24983,14 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {
|
|
24466
24983
|
background:white;
|
24467
24984
|
}
|
24468
24985
|
|
24469
|
-
.example-hide
|
24986
|
+
.example-hide {
|
24470
24987
|
line-height:20px;
|
24471
24988
|
opacity:1;
|
24472
24989
|
padding:10px;
|
24473
24990
|
border:1px solid black;
|
24474
24991
|
background:white;
|
24475
24992
|
}
|
24476
|
-
.example-hide-
|
24993
|
+
.example-hide-active.example-hide-active {
|
24477
24994
|
line-height:0;
|
24478
24995
|
opacity:0;
|
24479
24996
|
padding:0 10px;
|
@@ -24554,7 +25071,7 @@ var ngShowDirective = ['$animator', function($animator) {
|
|
24554
25071
|
</div>
|
24555
25072
|
</file>
|
24556
25073
|
<file name="animations.css">
|
24557
|
-
.example-show
|
25074
|
+
.example-show, .example-hide {
|
24558
25075
|
-webkit-transition:all linear 0.5s;
|
24559
25076
|
-moz-transition:all linear 0.5s;
|
24560
25077
|
-ms-transition:all linear 0.5s;
|
@@ -24562,12 +25079,12 @@ var ngShowDirective = ['$animator', function($animator) {
|
|
24562
25079
|
transition:all linear 0.5s;
|
24563
25080
|
}
|
24564
25081
|
|
24565
|
-
.example-show
|
25082
|
+
.example-show {
|
24566
25083
|
line-height:0;
|
24567
25084
|
opacity:0;
|
24568
25085
|
padding:0 10px;
|
24569
25086
|
}
|
24570
|
-
.example-show
|
25087
|
+
.example-show.example-show-active {
|
24571
25088
|
line-height:20px;
|
24572
25089
|
opacity:1;
|
24573
25090
|
padding:10px;
|
@@ -24575,14 +25092,14 @@ var ngShowDirective = ['$animator', function($animator) {
|
|
24575
25092
|
background:white;
|
24576
25093
|
}
|
24577
25094
|
|
24578
|
-
.example-hide
|
25095
|
+
.example-hide {
|
24579
25096
|
line-height:20px;
|
24580
25097
|
opacity:1;
|
24581
25098
|
padding:10px;
|
24582
25099
|
border:1px solid black;
|
24583
25100
|
background:white;
|
24584
25101
|
}
|
24585
|
-
.example-hide
|
25102
|
+
.example-hide.example-hide-active {
|
24586
25103
|
line-height:0;
|
24587
25104
|
opacity:0;
|
24588
25105
|
padding:0 10px;
|
@@ -24734,7 +25251,7 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
|
|
24734
25251
|
}
|
24735
25252
|
</file>
|
24736
25253
|
<file name="animations.css">
|
24737
|
-
.example-leave
|
25254
|
+
.example-leave, .example-enter {
|
24738
25255
|
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
24739
25256
|
-moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
24740
25257
|
-ms-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
@@ -24753,17 +25270,17 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
|
|
24753
25270
|
padding:10px;
|
24754
25271
|
}
|
24755
25272
|
|
24756
|
-
.example-enter
|
25273
|
+
.example-enter {
|
24757
25274
|
top:-50px;
|
24758
25275
|
}
|
24759
|
-
.example-enter
|
25276
|
+
.example-enter.example-enter-active {
|
24760
25277
|
top:0;
|
24761
25278
|
}
|
24762
25279
|
|
24763
|
-
.example-leave
|
25280
|
+
.example-leave {
|
24764
25281
|
top:0;
|
24765
25282
|
}
|
24766
|
-
.example-leave
|
25283
|
+
.example-leave.example-leave-active {
|
24767
25284
|
top:50px;
|
24768
25285
|
}
|
24769
25286
|
</file>
|
@@ -24929,7 +25446,7 @@ var ngTranscludeDirective = ngDirective({
|
|
24929
25446
|
* @example
|
24930
25447
|
<example module="ngView" animations="true">
|
24931
25448
|
<file name="index.html">
|
24932
|
-
<div ng-controller="MainCntl">
|
25449
|
+
<div ng-controller="MainCntl as main">
|
24933
25450
|
Choose:
|
24934
25451
|
<a href="Book/Moby">Moby</a> |
|
24935
25452
|
<a href="Book/Moby/ch/1">Moby: Ch1</a> |
|
@@ -24943,31 +25460,31 @@ var ngTranscludeDirective = ngDirective({
|
|
24943
25460
|
ng-animate="{enter: 'example-enter', leave: 'example-leave'}"></div>
|
24944
25461
|
<hr />
|
24945
25462
|
|
24946
|
-
<pre>$location.path() = {{
|
24947
|
-
<pre>$route.current.templateUrl = {{
|
24948
|
-
<pre>$route.current.params = {{
|
24949
|
-
<pre>$route.current.scope.name = {{
|
24950
|
-
<pre>$routeParams = {{
|
25463
|
+
<pre>$location.path() = {{main.$location.path()}}</pre>
|
25464
|
+
<pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>
|
25465
|
+
<pre>$route.current.params = {{main.$route.current.params}}</pre>
|
25466
|
+
<pre>$route.current.scope.name = {{main.$route.current.scope.name}}</pre>
|
25467
|
+
<pre>$routeParams = {{main.$routeParams}}</pre>
|
24951
25468
|
</div>
|
24952
25469
|
</file>
|
24953
25470
|
|
24954
25471
|
<file name="book.html">
|
24955
25472
|
<div>
|
24956
|
-
controller: {{name}}<br />
|
24957
|
-
Book Id: {{params.bookId}}<br />
|
25473
|
+
controller: {{book.name}}<br />
|
25474
|
+
Book Id: {{book.params.bookId}}<br />
|
24958
25475
|
</div>
|
24959
25476
|
</file>
|
24960
25477
|
|
24961
25478
|
<file name="chapter.html">
|
24962
25479
|
<div>
|
24963
|
-
controller: {{name}}<br />
|
24964
|
-
Book Id: {{params.bookId}}<br />
|
24965
|
-
Chapter Id: {{params.chapterId}}
|
25480
|
+
controller: {{chapter.name}}<br />
|
25481
|
+
Book Id: {{chapter.params.bookId}}<br />
|
25482
|
+
Chapter Id: {{chapter.params.chapterId}}
|
24966
25483
|
</div>
|
24967
25484
|
</file>
|
24968
25485
|
|
24969
25486
|
<file name="animations.css">
|
24970
|
-
.example-leave
|
25487
|
+
.example-leave, .example-enter {
|
24971
25488
|
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
|
24972
25489
|
-moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
|
24973
25490
|
-ms-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
|
@@ -24993,15 +25510,15 @@ var ngTranscludeDirective = ngDirective({
|
|
24993
25510
|
padding:10px;
|
24994
25511
|
}
|
24995
25512
|
|
24996
|
-
.example-enter
|
25513
|
+
.example-enter {
|
24997
25514
|
left:100%;
|
24998
25515
|
}
|
24999
|
-
.example-enter
|
25516
|
+
.example-enter.example-enter-active {
|
25000
25517
|
left:0;
|
25001
25518
|
}
|
25002
25519
|
|
25003
|
-
.example-leave
|
25004
|
-
.example-leave
|
25520
|
+
.example-leave { }
|
25521
|
+
.example-leave.example-leave-active {
|
25005
25522
|
left:-100%;
|
25006
25523
|
}
|
25007
25524
|
</file>
|
@@ -25010,31 +25527,33 @@ var ngTranscludeDirective = ngDirective({
|
|
25010
25527
|
angular.module('ngView', [], function($routeProvider, $locationProvider) {
|
25011
25528
|
$routeProvider.when('/Book/:bookId', {
|
25012
25529
|
templateUrl: 'book.html',
|
25013
|
-
controller: BookCntl
|
25530
|
+
controller: BookCntl,
|
25531
|
+
controllerAs: 'book'
|
25014
25532
|
});
|
25015
25533
|
$routeProvider.when('/Book/:bookId/ch/:chapterId', {
|
25016
25534
|
templateUrl: 'chapter.html',
|
25017
|
-
controller: ChapterCntl
|
25535
|
+
controller: ChapterCntl,
|
25536
|
+
controllerAs: 'chapter'
|
25018
25537
|
});
|
25019
25538
|
|
25020
25539
|
// configure html5 to get links working on jsfiddle
|
25021
25540
|
$locationProvider.html5Mode(true);
|
25022
25541
|
});
|
25023
25542
|
|
25024
|
-
function MainCntl($
|
25025
|
-
|
25026
|
-
|
25027
|
-
|
25543
|
+
function MainCntl($route, $routeParams, $location) {
|
25544
|
+
this.$route = $route;
|
25545
|
+
this.$location = $location;
|
25546
|
+
this.$routeParams = $routeParams;
|
25028
25547
|
}
|
25029
25548
|
|
25030
|
-
function BookCntl($
|
25031
|
-
|
25032
|
-
|
25549
|
+
function BookCntl($routeParams) {
|
25550
|
+
this.name = "BookCntl";
|
25551
|
+
this.params = $routeParams;
|
25033
25552
|
}
|
25034
25553
|
|
25035
|
-
function ChapterCntl($
|
25036
|
-
|
25037
|
-
|
25554
|
+
function ChapterCntl($routeParams) {
|
25555
|
+
this.name = "ChapterCntl";
|
25556
|
+
this.params = $routeParams;
|
25038
25557
|
}
|
25039
25558
|
</file>
|
25040
25559
|
|
@@ -25098,9 +25617,10 @@ var ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$c
|
|
25098
25617
|
|
25099
25618
|
if (template) {
|
25100
25619
|
clearContent();
|
25101
|
-
|
25620
|
+
var enterElements = jqLite('<div></div>').html(template).contents();
|
25621
|
+
animate.enter(enterElements, element);
|
25102
25622
|
|
25103
|
-
var link = $compile(
|
25623
|
+
var link = $compile(enterElements),
|
25104
25624
|
current = $route.current,
|
25105
25625
|
controller;
|
25106
25626
|
|
@@ -25108,6 +25628,9 @@ var ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$c
|
|
25108
25628
|
if (current.controller) {
|
25109
25629
|
locals.$scope = lastScope;
|
25110
25630
|
controller = $controller(current.controller, locals);
|
25631
|
+
if (current.controllerAs) {
|
25632
|
+
lastScope[current.controllerAs] = controller;
|
25633
|
+
}
|
25111
25634
|
element.children().data('$ngControllerController', controller);
|
25112
25635
|
}
|
25113
25636
|
|
@@ -25197,7 +25720,8 @@ var scriptDirective = ['$templateCache', function($templateCache) {
|
|
25197
25720
|
* `select` model to be bound to a non-string value. This is because an option element can currently
|
25198
25721
|
* be bound to string values only.
|
25199
25722
|
*
|
25200
|
-
* @param {string}
|
25723
|
+
* @param {string} ngModel Assignable angular expression to data-bind to.
|
25724
|
+
* @param {string=} name Property name of the form under which the control is published.
|
25201
25725
|
* @param {string=} required The control is considered valid only if value is entered.
|
25202
25726
|
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
|
25203
25727
|
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
|
@@ -25208,7 +25732,7 @@ var scriptDirective = ['$templateCache', function($templateCache) {
|
|
25208
25732
|
* * `label` **`for`** `value` **`in`** `array`
|
25209
25733
|
* * `select` **`as`** `label` **`for`** `value` **`in`** `array`
|
25210
25734
|
* * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
|
25211
|
-
* * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`
|
25735
|
+
* * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
|
25212
25736
|
* * for object data sources:
|
25213
25737
|
* * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
|
25214
25738
|
* * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
|
@@ -25228,6 +25752,9 @@ var scriptDirective = ['$templateCache', function($templateCache) {
|
|
25228
25752
|
* element. If not specified, `select` expression will default to `value`.
|
25229
25753
|
* * `group`: The result of this expression will be used to group options using the `<optgroup>`
|
25230
25754
|
* DOM element.
|
25755
|
+
* * `trackexpr`: Used when working with an array of objects. The result of this expression will be
|
25756
|
+
* used to identify the objects in the array. The `trackexpr` will most likely refer to the
|
25757
|
+
* `value` variable (e.g. `value.propertyName`).
|
25231
25758
|
*
|
25232
25759
|
* @example
|
25233
25760
|
<doc:example>
|
@@ -25292,8 +25819,8 @@ var scriptDirective = ['$templateCache', function($templateCache) {
|
|
25292
25819
|
|
25293
25820
|
var ngOptionsDirective = valueFn({ terminal: true });
|
25294
25821
|
var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
25295
|
-
//
|
25296
|
-
var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(
|
25822
|
+
//0000111110000000000022220000000000000000000000333300000000000000444444444444444440000000005555555555555555500000006666666666666666600000000000000007777000000000000000000088888
|
25823
|
+
var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/,
|
25297
25824
|
nullModelCtrl = {$setViewValue: noop};
|
25298
25825
|
|
25299
25826
|
return {
|
@@ -25467,7 +25994,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
25467
25994
|
|
25468
25995
|
if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {
|
25469
25996
|
throw Error(
|
25470
|
-
"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
|
25997
|
+
"Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_ (track by _expr_)?'" +
|
25471
25998
|
" but got '" + optionsExp + "'.");
|
25472
25999
|
}
|
25473
26000
|
|
@@ -25477,6 +26004,8 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
25477
26004
|
groupByFn = $parse(match[3] || ''),
|
25478
26005
|
valueFn = $parse(match[2] ? match[1] : valueName),
|
25479
26006
|
valuesFn = $parse(match[7]),
|
26007
|
+
track = match[8],
|
26008
|
+
trackFn = track ? $parse(match[8]) : null,
|
25480
26009
|
// This is an array of array of existing option groups in DOM. We try to reuse these if possible
|
25481
26010
|
// optionGroupsCache[0] is the options with no option group
|
25482
26011
|
// optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element
|
@@ -25517,7 +26046,14 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
25517
26046
|
if ((optionElement = optionGroup[index].element)[0].selected) {
|
25518
26047
|
key = optionElement.val();
|
25519
26048
|
if (keyName) locals[keyName] = key;
|
25520
|
-
|
26049
|
+
if (trackFn) {
|
26050
|
+
for (var trackIndex = 0; trackIndex < collection.length; trackIndex++) {
|
26051
|
+
locals[valueName] = collection[trackIndex];
|
26052
|
+
if (trackFn(scope, locals) == key) break;
|
26053
|
+
}
|
26054
|
+
} else {
|
26055
|
+
locals[valueName] = collection[key];
|
26056
|
+
}
|
25521
26057
|
value.push(valueFn(scope, locals));
|
25522
26058
|
}
|
25523
26059
|
}
|
@@ -25529,9 +26065,19 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
25529
26065
|
} else if (key == ''){
|
25530
26066
|
value = null;
|
25531
26067
|
} else {
|
25532
|
-
|
25533
|
-
|
25534
|
-
|
26068
|
+
if (trackFn) {
|
26069
|
+
for (var trackIndex = 0; trackIndex < collection.length; trackIndex++) {
|
26070
|
+
locals[valueName] = collection[trackIndex];
|
26071
|
+
if (trackFn(scope, locals) == key) {
|
26072
|
+
value = valueFn(scope, locals);
|
26073
|
+
break;
|
26074
|
+
}
|
26075
|
+
}
|
26076
|
+
} else {
|
26077
|
+
locals[valueName] = collection[key];
|
26078
|
+
if (keyName) locals[keyName] = key;
|
26079
|
+
value = valueFn(scope, locals);
|
26080
|
+
}
|
25535
26081
|
}
|
25536
26082
|
}
|
25537
26083
|
ctrl.$setViewValue(value);
|
@@ -25563,11 +26109,15 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
25563
26109
|
label;
|
25564
26110
|
|
25565
26111
|
if (multiple) {
|
25566
|
-
|
25567
|
-
|
25568
|
-
|
25569
|
-
|
25570
|
-
|
26112
|
+
if (trackFn && isArray(modelValue)) {
|
26113
|
+
selectedSet = new HashMap([]);
|
26114
|
+
for (var trackIndex = 0; trackIndex < modelValue.length; trackIndex++) {
|
26115
|
+
locals[valueName] = modelValue[trackIndex];
|
26116
|
+
selectedSet.put(trackFn(scope, locals), modelValue[trackIndex]);
|
26117
|
+
}
|
26118
|
+
} else {
|
26119
|
+
selectedSet = new HashMap(modelValue);
|
26120
|
+
}
|
25571
26121
|
}
|
25572
26122
|
|
25573
26123
|
// We now build up the list of options we need (we merge later)
|
@@ -25579,22 +26129,33 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
25579
26129
|
optionGroupNames.push(optionGroupName);
|
25580
26130
|
}
|
25581
26131
|
if (multiple) {
|
25582
|
-
selected = selectedSet.remove(valueFn(scope, locals)) != undefined;
|
26132
|
+
selected = selectedSet.remove(trackFn ? trackFn(scope, locals) : valueFn(scope, locals)) != undefined;
|
25583
26133
|
} else {
|
25584
|
-
|
26134
|
+
if (trackFn) {
|
26135
|
+
var modelCast = {};
|
26136
|
+
modelCast[valueName] = modelValue;
|
26137
|
+
selected = trackFn(scope, modelCast) === trackFn(scope, locals);
|
26138
|
+
} else {
|
26139
|
+
selected = modelValue === valueFn(scope, locals);
|
26140
|
+
}
|
25585
26141
|
selectedSet = selectedSet || selected; // see if at least one item is selected
|
25586
26142
|
}
|
25587
26143
|
label = displayFn(scope, locals); // what will be seen by the user
|
25588
26144
|
label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values
|
25589
26145
|
optionGroup.push({
|
25590
|
-
id: keyName ? keys[index] : index, // either the index into array or key from object
|
26146
|
+
id: trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index), // either the index into array or key from object
|
25591
26147
|
label: label,
|
25592
26148
|
selected: selected // determine if we should be selected
|
25593
26149
|
});
|
25594
26150
|
}
|
25595
|
-
if (!multiple
|
25596
|
-
|
25597
|
-
|
26151
|
+
if (!multiple) {
|
26152
|
+
if (nullOption || modelValue === null) {
|
26153
|
+
// insert null option if we have a placeholder, or the model is null
|
26154
|
+
optionGroups[''].unshift({id:'', label:'', selected:!selectedSet});
|
26155
|
+
} else if (!selectedSet) {
|
26156
|
+
// option could not be found, we have to insert the undefined item
|
26157
|
+
optionGroups[''].unshift({id:'?', label:'', selected:true});
|
26158
|
+
}
|
25598
26159
|
}
|
25599
26160
|
|
25600
26161
|
// Now we need to update the list of DOM nodes to match the optionGroups we computed above
|
@@ -25638,7 +26199,8 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
25638
26199
|
if (existingOption.id !== option.id) {
|
25639
26200
|
lastElement.val(existingOption.id = option.id);
|
25640
26201
|
}
|
25641
|
-
|
26202
|
+
// lastElement.prop('selected') provided by jQuery has side-effects
|
26203
|
+
if (lastElement[0].selected !== option.selected) {
|
25642
26204
|
lastElement.prop('selected', (existingOption.selected = option.selected));
|
25643
26205
|
}
|
25644
26206
|
} else {
|
@@ -25964,102 +26526,6 @@ function callerFile(offset) {
|
|
25964
26526
|
};
|
25965
26527
|
}
|
25966
26528
|
|
25967
|
-
/**
|
25968
|
-
* Triggers a browser event. Attempts to choose the right event if one is
|
25969
|
-
* not specified.
|
25970
|
-
*
|
25971
|
-
* @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement
|
25972
|
-
* @param {string} type Optional event type.
|
25973
|
-
* @param {Array.<string>=} keys Optional list of pressed keys
|
25974
|
-
* (valid values: 'alt', 'meta', 'shift', 'ctrl')
|
25975
|
-
* @param {number} x Optional x-coordinate for mouse/touch events.
|
25976
|
-
* @param {number} y Optional y-coordinate for mouse/touch events.
|
25977
|
-
*/
|
25978
|
-
function browserTrigger(element, type, keys, x, y) {
|
25979
|
-
if (element && !element.nodeName) element = element[0];
|
25980
|
-
if (!element) return;
|
25981
|
-
if (!type) {
|
25982
|
-
type = {
|
25983
|
-
'text': 'change',
|
25984
|
-
'textarea': 'change',
|
25985
|
-
'hidden': 'change',
|
25986
|
-
'password': 'change',
|
25987
|
-
'button': 'click',
|
25988
|
-
'submit': 'click',
|
25989
|
-
'reset': 'click',
|
25990
|
-
'image': 'click',
|
25991
|
-
'checkbox': 'click',
|
25992
|
-
'radio': 'click',
|
25993
|
-
'select-one': 'change',
|
25994
|
-
'select-multiple': 'change'
|
25995
|
-
}[lowercase(element.type)] || 'click';
|
25996
|
-
}
|
25997
|
-
if (lowercase(nodeName_(element)) == 'option') {
|
25998
|
-
element.parentNode.value = element.value;
|
25999
|
-
element = element.parentNode;
|
26000
|
-
type = 'change';
|
26001
|
-
}
|
26002
|
-
|
26003
|
-
keys = keys || [];
|
26004
|
-
function pressed(key) {
|
26005
|
-
return indexOf(keys, key) !== -1;
|
26006
|
-
}
|
26007
|
-
|
26008
|
-
if (msie < 9) {
|
26009
|
-
switch(element.type) {
|
26010
|
-
case 'radio':
|
26011
|
-
case 'checkbox':
|
26012
|
-
element.checked = !element.checked;
|
26013
|
-
break;
|
26014
|
-
}
|
26015
|
-
// WTF!!! Error: Unspecified error.
|
26016
|
-
// Don't know why, but some elements when detached seem to be in inconsistent state and
|
26017
|
-
// calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error)
|
26018
|
-
// forcing the browser to compute the element position (by reading its CSS)
|
26019
|
-
// puts the element in consistent state.
|
26020
|
-
element.style.posLeft;
|
26021
|
-
|
26022
|
-
// TODO(vojta): create event objects with pressed keys to get it working on IE<9
|
26023
|
-
var ret = element.fireEvent('on' + type);
|
26024
|
-
if (lowercase(element.type) == 'submit') {
|
26025
|
-
while(element) {
|
26026
|
-
if (lowercase(element.nodeName) == 'form') {
|
26027
|
-
element.fireEvent('onsubmit');
|
26028
|
-
break;
|
26029
|
-
}
|
26030
|
-
element = element.parentNode;
|
26031
|
-
}
|
26032
|
-
}
|
26033
|
-
return ret;
|
26034
|
-
} else {
|
26035
|
-
var evnt = document.createEvent('MouseEvents'),
|
26036
|
-
originalPreventDefault = evnt.preventDefault,
|
26037
|
-
iframe = _jQuery('#application iframe')[0],
|
26038
|
-
appWindow = iframe ? iframe.contentWindow : window,
|
26039
|
-
fakeProcessDefault = true,
|
26040
|
-
finalProcessDefault,
|
26041
|
-
angular = appWindow.angular || {};
|
26042
|
-
|
26043
|
-
// igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208
|
26044
|
-
angular['ff-684208-preventDefault'] = false;
|
26045
|
-
evnt.preventDefault = function() {
|
26046
|
-
fakeProcessDefault = false;
|
26047
|
-
return originalPreventDefault.apply(evnt, arguments);
|
26048
|
-
};
|
26049
|
-
|
26050
|
-
x = x || 0;
|
26051
|
-
y = y || 0;
|
26052
|
-
evnt.initMouseEvent(type, true, true, window, 0, x, y, x, y, pressed('ctrl'), pressed('alt'),
|
26053
|
-
pressed('shift'), pressed('meta'), 0, element);
|
26054
|
-
|
26055
|
-
element.dispatchEvent(evnt);
|
26056
|
-
finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);
|
26057
|
-
|
26058
|
-
delete angular['ff-684208-preventDefault'];
|
26059
|
-
|
26060
|
-
return finalProcessDefault;
|
26061
|
-
}
|
26062
|
-
}
|
26063
26529
|
|
26064
26530
|
/**
|
26065
26531
|
* Don't use the jQuery trigger method since it works incorrectly.
|
@@ -26073,7 +26539,7 @@ function browserTrigger(element, type, keys, x, y) {
|
|
26073
26539
|
(function(fn){
|
26074
26540
|
var parentTrigger = fn.trigger;
|
26075
26541
|
fn.trigger = function(type) {
|
26076
|
-
if (/(click|change|keydown|blur|input)/.test(type)) {
|
26542
|
+
if (/(click|change|keydown|blur|input|mousedown|mouseup)/.test(type)) {
|
26077
26543
|
var processDefaults = [];
|
26078
26544
|
this.each(function(index, node) {
|
26079
26545
|
processDefaults.push(browserTrigger(node, type));
|
@@ -26162,6 +26628,121 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
|
|
26162
26628
|
return result;
|
26163
26629
|
};
|
26164
26630
|
|
26631
|
+
(function() {
|
26632
|
+
var msie = parseInt((/msie (\d+)/.exec(navigator.userAgent.toLowerCase()) || [])[1], 10);
|
26633
|
+
|
26634
|
+
function indexOf(array, obj) {
|
26635
|
+
if (array.indexOf) return array.indexOf(obj);
|
26636
|
+
|
26637
|
+
for ( var i = 0; i < array.length; i++) {
|
26638
|
+
if (obj === array[i]) return i;
|
26639
|
+
}
|
26640
|
+
return -1;
|
26641
|
+
}
|
26642
|
+
|
26643
|
+
|
26644
|
+
|
26645
|
+
/**
|
26646
|
+
* Triggers a browser event. Attempts to choose the right event if one is
|
26647
|
+
* not specified.
|
26648
|
+
*
|
26649
|
+
* @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement
|
26650
|
+
* @param {string} eventType Optional event type.
|
26651
|
+
* @param {Array.<string>=} keys Optional list of pressed keys
|
26652
|
+
* (valid values: 'alt', 'meta', 'shift', 'ctrl')
|
26653
|
+
* @param {number} x Optional x-coordinate for mouse/touch events.
|
26654
|
+
* @param {number} y Optional y-coordinate for mouse/touch events.
|
26655
|
+
*/
|
26656
|
+
window.browserTrigger = function browserTrigger(element, eventType, keys, x, y) {
|
26657
|
+
if (element && !element.nodeName) element = element[0];
|
26658
|
+
if (!element) return;
|
26659
|
+
|
26660
|
+
var inputType = (element.type) ? element.type.toLowerCase() : null,
|
26661
|
+
nodeName = element.nodeName.toLowerCase();
|
26662
|
+
|
26663
|
+
if (!eventType) {
|
26664
|
+
eventType = {
|
26665
|
+
'text': 'change',
|
26666
|
+
'textarea': 'change',
|
26667
|
+
'hidden': 'change',
|
26668
|
+
'password': 'change',
|
26669
|
+
'button': 'click',
|
26670
|
+
'submit': 'click',
|
26671
|
+
'reset': 'click',
|
26672
|
+
'image': 'click',
|
26673
|
+
'checkbox': 'click',
|
26674
|
+
'radio': 'click',
|
26675
|
+
'select-one': 'change',
|
26676
|
+
'select-multiple': 'change',
|
26677
|
+
'_default_': 'click'
|
26678
|
+
}[inputType || '_default_'];
|
26679
|
+
}
|
26680
|
+
|
26681
|
+
if (nodeName == 'option') {
|
26682
|
+
element.parentNode.value = element.value;
|
26683
|
+
element = element.parentNode;
|
26684
|
+
eventType = 'change';
|
26685
|
+
}
|
26686
|
+
|
26687
|
+
keys = keys || [];
|
26688
|
+
function pressed(key) {
|
26689
|
+
return indexOf(keys, key) !== -1;
|
26690
|
+
}
|
26691
|
+
|
26692
|
+
if (msie < 9) {
|
26693
|
+
if (inputType == 'radio' || inputType == 'checkbox') {
|
26694
|
+
element.checked = !element.checked;
|
26695
|
+
}
|
26696
|
+
|
26697
|
+
// WTF!!! Error: Unspecified error.
|
26698
|
+
// Don't know why, but some elements when detached seem to be in inconsistent state and
|
26699
|
+
// calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error)
|
26700
|
+
// forcing the browser to compute the element position (by reading its CSS)
|
26701
|
+
// puts the element in consistent state.
|
26702
|
+
element.style.posLeft;
|
26703
|
+
|
26704
|
+
// TODO(vojta): create event objects with pressed keys to get it working on IE<9
|
26705
|
+
var ret = element.fireEvent('on' + eventType);
|
26706
|
+
if (inputType == 'submit') {
|
26707
|
+
while(element) {
|
26708
|
+
if (element.nodeName.toLowerCase() == 'form') {
|
26709
|
+
element.fireEvent('onsubmit');
|
26710
|
+
break;
|
26711
|
+
}
|
26712
|
+
element = element.parentNode;
|
26713
|
+
}
|
26714
|
+
}
|
26715
|
+
return ret;
|
26716
|
+
} else {
|
26717
|
+
var evnt = document.createEvent('MouseEvents'),
|
26718
|
+
originalPreventDefault = evnt.preventDefault,
|
26719
|
+
appWindow = element.ownerDocument.defaultView,
|
26720
|
+
fakeProcessDefault = true,
|
26721
|
+
finalProcessDefault,
|
26722
|
+
angular = appWindow.angular || {};
|
26723
|
+
|
26724
|
+
// igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208
|
26725
|
+
angular['ff-684208-preventDefault'] = false;
|
26726
|
+
evnt.preventDefault = function() {
|
26727
|
+
fakeProcessDefault = false;
|
26728
|
+
return originalPreventDefault.apply(evnt, arguments);
|
26729
|
+
};
|
26730
|
+
|
26731
|
+
x = x || 0;
|
26732
|
+
y = y || 0;
|
26733
|
+
evnt.initMouseEvent(eventType, true, true, window, 0, x, y, x, y, pressed('ctrl'), pressed('alt'),
|
26734
|
+
pressed('shift'), pressed('meta'), 0, element);
|
26735
|
+
|
26736
|
+
element.dispatchEvent(evnt);
|
26737
|
+
finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);
|
26738
|
+
|
26739
|
+
delete angular['ff-684208-preventDefault'];
|
26740
|
+
|
26741
|
+
return finalProcessDefault;
|
26742
|
+
}
|
26743
|
+
}
|
26744
|
+
}());
|
26745
|
+
|
26165
26746
|
/**
|
26166
26747
|
* Represents the application currently being tested and abstracts usage
|
26167
26748
|
* of iframes or separate windows.
|
@@ -26225,8 +26806,6 @@ angular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorF
|
|
26225
26806
|
self.context.find('#test-frames').append('<iframe>');
|
26226
26807
|
frame = self.getFrame_();
|
26227
26808
|
|
26228
|
-
frame[0].contentWindow.name = "NG_DEFER_BOOTSTRAP!";
|
26229
|
-
|
26230
26809
|
frame.load(function() {
|
26231
26810
|
frame.unbind();
|
26232
26811
|
try {
|
@@ -26239,7 +26818,8 @@ angular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorF
|
|
26239
26818
|
// we don't need that for our tests, but it should be done
|
26240
26819
|
$window.angular.resumeBootstrap([['$provide', function($provide) {
|
26241
26820
|
$provide.decorator('$sniffer', function($delegate) {
|
26242
|
-
$delegate.
|
26821
|
+
$delegate.transitions = false;
|
26822
|
+
$delegate.animations = false;
|
26243
26823
|
return $delegate;
|
26244
26824
|
});
|
26245
26825
|
}]]);
|
@@ -26250,6 +26830,9 @@ angular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorF
|
|
26250
26830
|
errorFn(e);
|
26251
26831
|
}
|
26252
26832
|
}).attr('src', url);
|
26833
|
+
|
26834
|
+
// for IE compatibility set the name *after* setting the frame url
|
26835
|
+
frame[0].contentWindow.name = "NG_DEFER_BOOTSTRAP!";
|
26253
26836
|
}
|
26254
26837
|
self.context.find('> h2 a').attr('href', url).text(url);
|
26255
26838
|
};
|
@@ -27452,6 +28035,8 @@ angular.scenario.dsl('select', function() {
|
|
27452
28035
|
* element(selector, label).count() get the number of elements that match selector
|
27453
28036
|
* element(selector, label).click() clicks an element
|
27454
28037
|
* element(selector, label).mouseover() mouseover an element
|
28038
|
+
* element(selector, label).mousedown() mousedown an element
|
28039
|
+
* element(selector, label).mouseup() mouseup an element
|
27455
28040
|
* element(selector, label).query(fn) executes fn(selectedElements, done)
|
27456
28041
|
* element(selector, label).{method}() gets the value (as defined by jQuery, ex. val)
|
27457
28042
|
* element(selector, label).{method}(value) sets the value (as defined by jQuery, ex. val)
|
@@ -27516,6 +28101,22 @@ angular.scenario.dsl('element', function() {
|
|
27516
28101
|
});
|
27517
28102
|
};
|
27518
28103
|
|
28104
|
+
chain.mousedown = function() {
|
28105
|
+
return this.addFutureAction("element '" + this.label + "' mousedown", function($window, $document, done) {
|
28106
|
+
var elements = $document.elements();
|
28107
|
+
elements.trigger('mousedown');
|
28108
|
+
done();
|
28109
|
+
});
|
28110
|
+
};
|
28111
|
+
|
28112
|
+
chain.mouseup = function() {
|
28113
|
+
return this.addFutureAction("element '" + this.label + "' mouseup", function($window, $document, done) {
|
28114
|
+
var elements = $document.elements();
|
28115
|
+
elements.trigger('mouseup');
|
28116
|
+
done();
|
28117
|
+
});
|
28118
|
+
};
|
28119
|
+
|
27519
28120
|
chain.query = function(fn) {
|
27520
28121
|
return this.addFutureAction('element ' + this.label + ' custom query', function($window, $document, done) {
|
27521
28122
|
fn.call(this, $document.elements(), done);
|