angularjs-rails 1.0.6.2 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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);
|