angularjs-on-rails 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/assets/javascripts/angular-animate.js +77 -21
- data/app/assets/javascripts/angular-cookies.js +17 -15
- data/app/assets/javascripts/angular-loader.js +2 -2
- data/app/assets/javascripts/angular-mocks.js +11 -3
- data/app/assets/javascripts/angular-resource.js +12 -12
- data/app/assets/javascripts/angular-route.js +2 -4
- data/app/assets/javascripts/angular-sanitize.js +40 -30
- data/app/assets/javascripts/angular-scenario.js +909 -744
- data/app/assets/javascripts/angular-touch.js +1 -1
- data/app/assets/javascripts/angular.js +908 -743
- data/lib/angularjs-on-rails/version.rb +1 -1
- data/lib/generators/angular/install/templates/index.html +0 -1
- metadata +4 -4
@@ -9790,7 +9790,7 @@ if ( typeof module === "object" && module && typeof module.exports === "object"
|
|
9790
9790
|
})( window );
|
9791
9791
|
|
9792
9792
|
/**
|
9793
|
-
* @license AngularJS v1.2.
|
9793
|
+
* @license AngularJS v1.2.21
|
9794
9794
|
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
9795
9795
|
* License: MIT
|
9796
9796
|
*/
|
@@ -9860,7 +9860,7 @@ function minErr(module) {
|
|
9860
9860
|
return match;
|
9861
9861
|
});
|
9862
9862
|
|
9863
|
-
message = message + '\nhttp://errors.angularjs.org/1.2.
|
9863
|
+
message = message + '\nhttp://errors.angularjs.org/1.2.21/' +
|
9864
9864
|
(module ? module + '/' : '') + code;
|
9865
9865
|
for (i = 2; i < arguments.length; i++) {
|
9866
9866
|
message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
|
@@ -9872,88 +9872,88 @@ function minErr(module) {
|
|
9872
9872
|
}
|
9873
9873
|
|
9874
9874
|
/* We need to tell jshint what variables are being exported */
|
9875
|
-
/* global
|
9876
|
-
|
9877
|
-
|
9878
|
-
|
9879
|
-
|
9880
|
-
|
9881
|
-
|
9882
|
-
|
9883
|
-
|
9884
|
-
|
9885
|
-
|
9886
|
-
|
9887
|
-
|
9888
|
-
|
9889
|
-
|
9890
|
-
|
9891
|
-
|
9892
|
-
|
9893
|
-
|
9894
|
-
|
9895
|
-
|
9896
|
-
|
9897
|
-
|
9898
|
-
|
9899
|
-
|
9900
|
-
|
9901
|
-
|
9902
|
-
|
9903
|
-
|
9904
|
-
|
9905
|
-
|
9906
|
-
|
9907
|
-
|
9908
|
-
|
9909
|
-
|
9910
|
-
|
9911
|
-
|
9912
|
-
|
9913
|
-
|
9914
|
-
|
9915
|
-
|
9916
|
-
|
9917
|
-
|
9918
|
-
|
9919
|
-
|
9920
|
-
|
9921
|
-
|
9922
|
-
|
9923
|
-
|
9924
|
-
|
9925
|
-
|
9926
|
-
|
9927
|
-
|
9928
|
-
|
9929
|
-
|
9930
|
-
|
9931
|
-
|
9932
|
-
|
9933
|
-
|
9934
|
-
|
9935
|
-
|
9936
|
-
|
9937
|
-
|
9938
|
-
|
9939
|
-
|
9940
|
-
|
9941
|
-
|
9942
|
-
|
9943
|
-
|
9944
|
-
|
9945
|
-
|
9946
|
-
|
9947
|
-
|
9948
|
-
|
9949
|
-
|
9950
|
-
|
9951
|
-
|
9952
|
-
|
9953
|
-
|
9954
|
-
|
9955
|
-
|
9956
|
-
|
9875
|
+
/* global angular: true,
|
9876
|
+
msie: true,
|
9877
|
+
jqLite: true,
|
9878
|
+
jQuery: true,
|
9879
|
+
slice: true,
|
9880
|
+
push: true,
|
9881
|
+
toString: true,
|
9882
|
+
ngMinErr: true,
|
9883
|
+
angularModule: true,
|
9884
|
+
nodeName_: true,
|
9885
|
+
uid: true,
|
9886
|
+
VALIDITY_STATE_PROPERTY: true,
|
9887
|
+
|
9888
|
+
lowercase: true,
|
9889
|
+
uppercase: true,
|
9890
|
+
manualLowercase: true,
|
9891
|
+
manualUppercase: true,
|
9892
|
+
nodeName_: true,
|
9893
|
+
isArrayLike: true,
|
9894
|
+
forEach: true,
|
9895
|
+
sortedKeys: true,
|
9896
|
+
forEachSorted: true,
|
9897
|
+
reverseParams: true,
|
9898
|
+
nextUid: true,
|
9899
|
+
setHashKey: true,
|
9900
|
+
extend: true,
|
9901
|
+
int: true,
|
9902
|
+
inherit: true,
|
9903
|
+
noop: true,
|
9904
|
+
identity: true,
|
9905
|
+
valueFn: true,
|
9906
|
+
isUndefined: true,
|
9907
|
+
isDefined: true,
|
9908
|
+
isObject: true,
|
9909
|
+
isString: true,
|
9910
|
+
isNumber: true,
|
9911
|
+
isDate: true,
|
9912
|
+
isArray: true,
|
9913
|
+
isFunction: true,
|
9914
|
+
isRegExp: true,
|
9915
|
+
isWindow: true,
|
9916
|
+
isScope: true,
|
9917
|
+
isFile: true,
|
9918
|
+
isBlob: true,
|
9919
|
+
isBoolean: true,
|
9920
|
+
isPromiseLike: true,
|
9921
|
+
trim: true,
|
9922
|
+
isElement: true,
|
9923
|
+
makeMap: true,
|
9924
|
+
map: true,
|
9925
|
+
size: true,
|
9926
|
+
includes: true,
|
9927
|
+
indexOf: true,
|
9928
|
+
arrayRemove: true,
|
9929
|
+
isLeafNode: true,
|
9930
|
+
copy: true,
|
9931
|
+
shallowCopy: true,
|
9932
|
+
equals: true,
|
9933
|
+
csp: true,
|
9934
|
+
concat: true,
|
9935
|
+
sliceArgs: true,
|
9936
|
+
bind: true,
|
9937
|
+
toJsonReplacer: true,
|
9938
|
+
toJson: true,
|
9939
|
+
fromJson: true,
|
9940
|
+
toBoolean: true,
|
9941
|
+
startingTag: true,
|
9942
|
+
tryDecodeURIComponent: true,
|
9943
|
+
parseKeyValue: true,
|
9944
|
+
toKeyValue: true,
|
9945
|
+
encodeUriSegment: true,
|
9946
|
+
encodeUriQuery: true,
|
9947
|
+
angularInit: true,
|
9948
|
+
bootstrap: true,
|
9949
|
+
snake_case: true,
|
9950
|
+
bindJQuery: true,
|
9951
|
+
assertArg: true,
|
9952
|
+
assertArgFn: true,
|
9953
|
+
assertNotHasOwnProperty: true,
|
9954
|
+
getter: true,
|
9955
|
+
getBlockElements: true,
|
9956
|
+
hasOwnProperty: true,
|
9957
9957
|
*/
|
9958
9958
|
|
9959
9959
|
////////////////////////////////////
|
@@ -9973,6 +9973,10 @@ function minErr(module) {
|
|
9973
9973
|
* <div doc-module-components="ng"></div>
|
9974
9974
|
*/
|
9975
9975
|
|
9976
|
+
// The name of a form control's ValidityState property.
|
9977
|
+
// This is used so that it's possible for internal tests to create mock ValidityStates.
|
9978
|
+
var VALIDITY_STATE_PROPERTY = 'validity';
|
9979
|
+
|
9976
9980
|
/**
|
9977
9981
|
* @ngdoc function
|
9978
9982
|
* @name angular.lowercase
|
@@ -10108,11 +10112,12 @@ function forEach(obj, iterator, context) {
|
|
10108
10112
|
iterator.call(context, obj[key], key);
|
10109
10113
|
}
|
10110
10114
|
}
|
10111
|
-
} else if (obj
|
10112
|
-
obj.
|
10113
|
-
} else if (isArrayLike(obj)) {
|
10114
|
-
for (key = 0; key < obj.length; key++)
|
10115
|
+
} else if (isArray(obj) || isArrayLike(obj)) {
|
10116
|
+
for (key = 0; key < obj.length; key++) {
|
10115
10117
|
iterator.call(context, obj[key], key);
|
10118
|
+
}
|
10119
|
+
} else if (obj.forEach && obj.forEach !== forEach) {
|
10120
|
+
obj.forEach(iterator, context);
|
10116
10121
|
} else {
|
10117
10122
|
for (key in obj) {
|
10118
10123
|
if (obj.hasOwnProperty(key)) {
|
@@ -10449,6 +10454,11 @@ function isBoolean(value) {
|
|
10449
10454
|
}
|
10450
10455
|
|
10451
10456
|
|
10457
|
+
function isPromiseLike(obj) {
|
10458
|
+
return obj && isFunction(obj.then);
|
10459
|
+
}
|
10460
|
+
|
10461
|
+
|
10452
10462
|
var trim = (function() {
|
10453
10463
|
// native trim is way faster: http://jsperf.com/angular-trim-test
|
10454
10464
|
// but IE doesn't have it... :-(
|
@@ -10597,9 +10607,9 @@ function isLeafNode (node) {
|
|
10597
10607
|
* @returns {*} The copy or updated `destination`, if `destination` was specified.
|
10598
10608
|
*
|
10599
10609
|
* @example
|
10600
|
-
<example>
|
10610
|
+
<example module="copyExample">
|
10601
10611
|
<file name="index.html">
|
10602
|
-
<div ng-controller="
|
10612
|
+
<div ng-controller="ExampleController">
|
10603
10613
|
<form novalidate class="simple-form">
|
10604
10614
|
Name: <input type="text" ng-model="user.name" /><br />
|
10605
10615
|
E-mail: <input type="email" ng-model="user.email" /><br />
|
@@ -10613,21 +10623,22 @@ function isLeafNode (node) {
|
|
10613
10623
|
</div>
|
10614
10624
|
|
10615
10625
|
<script>
|
10616
|
-
|
10617
|
-
$scope
|
10626
|
+
angular.module('copyExample', [])
|
10627
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
10628
|
+
$scope.master= {};
|
10618
10629
|
|
10619
|
-
|
10620
|
-
|
10621
|
-
|
10622
|
-
|
10630
|
+
$scope.update = function(user) {
|
10631
|
+
// Example with 1 argument
|
10632
|
+
$scope.master= angular.copy(user);
|
10633
|
+
};
|
10623
10634
|
|
10624
|
-
|
10625
|
-
|
10626
|
-
|
10627
|
-
|
10635
|
+
$scope.reset = function() {
|
10636
|
+
// Example with 2 arguments
|
10637
|
+
angular.copy($scope.master, $scope.user);
|
10638
|
+
};
|
10628
10639
|
|
10629
|
-
|
10630
|
-
|
10640
|
+
$scope.reset();
|
10641
|
+
}]);
|
10631
10642
|
</script>
|
10632
10643
|
</file>
|
10633
10644
|
</example>
|
@@ -10646,7 +10657,8 @@ function copy(source, destination, stackSource, stackDest) {
|
|
10646
10657
|
} else if (isDate(source)) {
|
10647
10658
|
destination = new Date(source.getTime());
|
10648
10659
|
} else if (isRegExp(source)) {
|
10649
|
-
destination = new RegExp(source.source);
|
10660
|
+
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
|
10661
|
+
destination.lastIndex = source.lastIndex;
|
10650
10662
|
} else if (isObject(source)) {
|
10651
10663
|
destination = copy(source, {}, stackSource, stackDest);
|
10652
10664
|
}
|
@@ -10790,12 +10802,25 @@ function equals(o1, o2) {
|
|
10790
10802
|
return false;
|
10791
10803
|
}
|
10792
10804
|
|
10805
|
+
var csp = function() {
|
10806
|
+
if (isDefined(csp.isActive_)) return csp.isActive_;
|
10807
|
+
|
10808
|
+
var active = !!(document.querySelector('[ng-csp]') ||
|
10809
|
+
document.querySelector('[data-ng-csp]'));
|
10810
|
+
|
10811
|
+
if (!active) {
|
10812
|
+
try {
|
10813
|
+
/* jshint -W031, -W054 */
|
10814
|
+
new Function('');
|
10815
|
+
/* jshint +W031, +W054 */
|
10816
|
+
} catch (e) {
|
10817
|
+
active = true;
|
10818
|
+
}
|
10819
|
+
}
|
10820
|
+
|
10821
|
+
return (csp.isActive_ = active);
|
10822
|
+
};
|
10793
10823
|
|
10794
|
-
function csp() {
|
10795
|
-
return (document.securityPolicy && document.securityPolicy.isActive) ||
|
10796
|
-
(document.querySelector &&
|
10797
|
-
!!(document.querySelector('[ng-csp]') || document.querySelector('[data-ng-csp]')));
|
10798
|
-
}
|
10799
10824
|
|
10800
10825
|
|
10801
10826
|
function concat(array1, array2, index) {
|
@@ -10967,11 +10992,11 @@ function parseKeyValue(/**string*/keyValue) {
|
|
10967
10992
|
var obj = {}, key_value, key;
|
10968
10993
|
forEach((keyValue || "").split('&'), function(keyValue) {
|
10969
10994
|
if ( keyValue ) {
|
10970
|
-
key_value = keyValue.split('=');
|
10995
|
+
key_value = keyValue.replace(/\+/g,'%20').split('=');
|
10971
10996
|
key = tryDecodeURIComponent(key_value[0]);
|
10972
10997
|
if ( isDefined(key) ) {
|
10973
10998
|
var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
|
10974
|
-
if (!obj
|
10999
|
+
if (!hasOwnProperty.call(obj, key)) {
|
10975
11000
|
obj[key] = val;
|
10976
11001
|
} else if(isArray(obj[key])) {
|
10977
11002
|
obj[key].push(val);
|
@@ -11145,7 +11170,7 @@ function angularInit(element, bootstrap) {
|
|
11145
11170
|
*
|
11146
11171
|
* Angular will detect if it has been loaded into the browser more than once and only allow the
|
11147
11172
|
* first loaded script to be bootstrapped and will report a warning to the browser console for
|
11148
|
-
* each of the subsequent scripts.
|
11173
|
+
* each of the subsequent scripts. This prevents strange results in applications, where otherwise
|
11149
11174
|
* multiple instances of Angular try to work on the DOM.
|
11150
11175
|
*
|
11151
11176
|
* <example name="multi-bootstrap" module="multi-bootstrap">
|
@@ -11275,7 +11300,7 @@ function assertArgFn(arg, name, acceptArrayAnnotation) {
|
|
11275
11300
|
}
|
11276
11301
|
|
11277
11302
|
assertArg(isFunction(arg), name, 'not a function, got ' +
|
11278
|
-
(arg && typeof arg
|
11303
|
+
(arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));
|
11279
11304
|
return arg;
|
11280
11305
|
}
|
11281
11306
|
|
@@ -11652,12 +11677,11 @@ function setupModuleLoader(window) {
|
|
11652
11677
|
|
11653
11678
|
}
|
11654
11679
|
|
11655
|
-
/* global
|
11656
|
-
|
11657
|
-
version: true,
|
11680
|
+
/* global angularModule: true,
|
11681
|
+
version: true,
|
11658
11682
|
|
11659
|
-
|
11660
|
-
|
11683
|
+
$LocaleProvider,
|
11684
|
+
$CompileProvider,
|
11661
11685
|
|
11662
11686
|
htmlAnchorDirective,
|
11663
11687
|
inputDirective,
|
@@ -11745,11 +11769,11 @@ function setupModuleLoader(window) {
|
|
11745
11769
|
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
|
11746
11770
|
*/
|
11747
11771
|
var version = {
|
11748
|
-
full: '1.2.
|
11772
|
+
full: '1.2.21', // all of these placeholder strings will be replaced by grunt's
|
11749
11773
|
major: 1, // package task
|
11750
11774
|
minor: 2,
|
11751
|
-
dot:
|
11752
|
-
codeName: '
|
11775
|
+
dot: 21,
|
11776
|
+
codeName: 'wizard-props'
|
11753
11777
|
};
|
11754
11778
|
|
11755
11779
|
|
@@ -11873,12 +11897,10 @@ function publishExternalAPI(angular){
|
|
11873
11897
|
]);
|
11874
11898
|
}
|
11875
11899
|
|
11876
|
-
/* global
|
11877
|
-
|
11878
|
-
|
11879
|
-
|
11880
|
-
-removeEventListenerFn,
|
11881
|
-
-BOOLEAN_ATTR
|
11900
|
+
/* global JQLitePrototype: true,
|
11901
|
+
addEventListenerFn: true,
|
11902
|
+
removeEventListenerFn: true,
|
11903
|
+
BOOLEAN_ATTR: true
|
11882
11904
|
*/
|
11883
11905
|
|
11884
11906
|
//////////////////////////////////
|
@@ -11971,8 +11993,9 @@ function publishExternalAPI(angular){
|
|
11971
11993
|
* @returns {Object} jQuery object.
|
11972
11994
|
*/
|
11973
11995
|
|
11996
|
+
JQLite.expando = 'ng339';
|
11997
|
+
|
11974
11998
|
var jqCache = JQLite.cache = {},
|
11975
|
-
jqName = JQLite.expando = 'ng' + new Date().getTime(),
|
11976
11999
|
jqId = 1,
|
11977
12000
|
addEventListenerFn = (window.document.addEventListener
|
11978
12001
|
? function(element, type, fn) {element.addEventListener(type, fn, false);}
|
@@ -12182,7 +12205,7 @@ function jqLiteOff(element, type, fn, unsupported) {
|
|
12182
12205
|
}
|
12183
12206
|
|
12184
12207
|
function jqLiteRemoveData(element, name) {
|
12185
|
-
var expandoId = element
|
12208
|
+
var expandoId = element.ng339,
|
12186
12209
|
expandoStore = jqCache[expandoId];
|
12187
12210
|
|
12188
12211
|
if (expandoStore) {
|
@@ -12196,17 +12219,17 @@ function jqLiteRemoveData(element, name) {
|
|
12196
12219
|
jqLiteOff(element);
|
12197
12220
|
}
|
12198
12221
|
delete jqCache[expandoId];
|
12199
|
-
element
|
12222
|
+
element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it
|
12200
12223
|
}
|
12201
12224
|
}
|
12202
12225
|
|
12203
12226
|
function jqLiteExpandoStore(element, key, value) {
|
12204
|
-
var expandoId = element
|
12227
|
+
var expandoId = element.ng339,
|
12205
12228
|
expandoStore = jqCache[expandoId || -1];
|
12206
12229
|
|
12207
12230
|
if (isDefined(value)) {
|
12208
12231
|
if (!expandoStore) {
|
12209
|
-
element
|
12232
|
+
element.ng339 = expandoId = jqNextId();
|
12210
12233
|
expandoStore = jqCache[expandoId] = {};
|
12211
12234
|
}
|
12212
12235
|
expandoStore[key] = value;
|
@@ -12291,25 +12314,22 @@ function jqLiteController(element, name) {
|
|
12291
12314
|
}
|
12292
12315
|
|
12293
12316
|
function jqLiteInheritedData(element, name, value) {
|
12294
|
-
element = jqLite(element);
|
12295
|
-
|
12296
12317
|
// if element is the document object work with the html element instead
|
12297
12318
|
// this makes $(document).scope() possible
|
12298
|
-
if(element
|
12299
|
-
element = element.
|
12319
|
+
if(element.nodeType == 9) {
|
12320
|
+
element = element.documentElement;
|
12300
12321
|
}
|
12301
12322
|
var names = isArray(name) ? name : [name];
|
12302
12323
|
|
12303
|
-
while (element
|
12304
|
-
var node = element[0];
|
12324
|
+
while (element) {
|
12305
12325
|
for (var i = 0, ii = names.length; i < ii; i++) {
|
12306
|
-
if ((value =
|
12326
|
+
if ((value = jqLite.data(element, names[i])) !== undefined) return value;
|
12307
12327
|
}
|
12308
12328
|
|
12309
12329
|
// If dealing with a document fragment node with a host element, and no parent, use the host
|
12310
12330
|
// element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
|
12311
12331
|
// to lookup parent controllers.
|
12312
|
-
element =
|
12332
|
+
element = element.parentNode || (element.nodeType === 11 && element.host);
|
12313
12333
|
}
|
12314
12334
|
}
|
12315
12335
|
|
@@ -12384,18 +12404,25 @@ function getBooleanAttrName(element, name) {
|
|
12384
12404
|
return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;
|
12385
12405
|
}
|
12386
12406
|
|
12407
|
+
forEach({
|
12408
|
+
data: jqLiteData,
|
12409
|
+
removeData: jqLiteRemoveData
|
12410
|
+
}, function(fn, name) {
|
12411
|
+
JQLite[name] = fn;
|
12412
|
+
});
|
12413
|
+
|
12387
12414
|
forEach({
|
12388
12415
|
data: jqLiteData,
|
12389
12416
|
inheritedData: jqLiteInheritedData,
|
12390
12417
|
|
12391
12418
|
scope: function(element) {
|
12392
12419
|
// Can't use jqLiteData here directly so we stay compatible with jQuery!
|
12393
|
-
return jqLite
|
12420
|
+
return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);
|
12394
12421
|
},
|
12395
12422
|
|
12396
12423
|
isolateScope: function(element) {
|
12397
12424
|
// Can't use jqLiteData here directly so we stay compatible with jQuery!
|
12398
|
-
return jqLite
|
12425
|
+
return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');
|
12399
12426
|
},
|
12400
12427
|
|
12401
12428
|
controller: jqLiteController,
|
@@ -12823,7 +12850,9 @@ forEach({
|
|
12823
12850
|
clone: jqLiteClone,
|
12824
12851
|
|
12825
12852
|
triggerHandler: function(element, eventName, eventData) {
|
12826
|
-
|
12853
|
+
// Copy event handlers in case event handlers array is modified during execution.
|
12854
|
+
var eventFns = (jqLiteExpandoStore(element, 'events') || {})[eventName],
|
12855
|
+
eventFnsCopy = shallowCopy(eventFns || []);
|
12827
12856
|
|
12828
12857
|
eventData = eventData || [];
|
12829
12858
|
|
@@ -12832,7 +12861,7 @@ forEach({
|
|
12832
12861
|
stopPropagation: noop
|
12833
12862
|
}];
|
12834
12863
|
|
12835
|
-
forEach(
|
12864
|
+
forEach(eventFnsCopy, function(fn) {
|
12836
12865
|
fn.apply(element, event.concat(eventData));
|
12837
12866
|
});
|
12838
12867
|
}
|
@@ -12873,16 +12902,16 @@ forEach({
|
|
12873
12902
|
* @returns {string} hash string such that the same input will have the same hash string.
|
12874
12903
|
* The resulting string key is in 'type:hashKey' format.
|
12875
12904
|
*/
|
12876
|
-
function hashKey(obj) {
|
12905
|
+
function hashKey(obj, nextUidFn) {
|
12877
12906
|
var objType = typeof obj,
|
12878
12907
|
key;
|
12879
12908
|
|
12880
|
-
if (objType == 'object' && obj !== null) {
|
12909
|
+
if (objType == 'function' || (objType == 'object' && obj !== null)) {
|
12881
12910
|
if (typeof (key = obj.$$hashKey) == 'function') {
|
12882
12911
|
// must invoke on object to keep the right this
|
12883
12912
|
key = obj.$$hashKey();
|
12884
12913
|
} else if (key === undefined) {
|
12885
|
-
key = obj.$$hashKey = nextUid();
|
12914
|
+
key = obj.$$hashKey = (nextUidFn || nextUid)();
|
12886
12915
|
}
|
12887
12916
|
} else {
|
12888
12917
|
key = obj;
|
@@ -12894,7 +12923,13 @@ function hashKey(obj) {
|
|
12894
12923
|
/**
|
12895
12924
|
* HashMap which can use objects as keys
|
12896
12925
|
*/
|
12897
|
-
function HashMap(array){
|
12926
|
+
function HashMap(array, isolatedUid) {
|
12927
|
+
if (isolatedUid) {
|
12928
|
+
var uid = 0;
|
12929
|
+
this.nextUid = function() {
|
12930
|
+
return ++uid;
|
12931
|
+
};
|
12932
|
+
}
|
12898
12933
|
forEach(array, this.put, this);
|
12899
12934
|
}
|
12900
12935
|
HashMap.prototype = {
|
@@ -12904,7 +12939,7 @@ HashMap.prototype = {
|
|
12904
12939
|
* @param value value to store can be any type
|
12905
12940
|
*/
|
12906
12941
|
put: function(key, value) {
|
12907
|
-
this[hashKey(key)] = value;
|
12942
|
+
this[hashKey(key, this.nextUid)] = value;
|
12908
12943
|
},
|
12909
12944
|
|
12910
12945
|
/**
|
@@ -12912,7 +12947,7 @@ HashMap.prototype = {
|
|
12912
12947
|
* @returns {Object} the value for the key
|
12913
12948
|
*/
|
12914
12949
|
get: function(key) {
|
12915
|
-
return this[hashKey(key)];
|
12950
|
+
return this[hashKey(key, this.nextUid)];
|
12916
12951
|
},
|
12917
12952
|
|
12918
12953
|
/**
|
@@ -12920,7 +12955,7 @@ HashMap.prototype = {
|
|
12920
12955
|
* @param key
|
12921
12956
|
*/
|
12922
12957
|
remove: function(key) {
|
12923
|
-
var value = this[key = hashKey(key)];
|
12958
|
+
var value = this[key = hashKey(key, this.nextUid)];
|
12924
12959
|
delete this[key];
|
12925
12960
|
return value;
|
12926
12961
|
}
|
@@ -12998,7 +13033,7 @@ function annotate(fn) {
|
|
12998
13033
|
argDecl,
|
12999
13034
|
last;
|
13000
13035
|
|
13001
|
-
if (typeof fn
|
13036
|
+
if (typeof fn === 'function') {
|
13002
13037
|
if (!($inject = fn.$inject)) {
|
13003
13038
|
$inject = [];
|
13004
13039
|
if (fn.length) {
|
@@ -13211,7 +13246,7 @@ function annotate(fn) {
|
|
13211
13246
|
|
13212
13247
|
|
13213
13248
|
/**
|
13214
|
-
* @ngdoc
|
13249
|
+
* @ngdoc service
|
13215
13250
|
* @name $provide
|
13216
13251
|
*
|
13217
13252
|
* @description
|
@@ -13517,7 +13552,7 @@ function createInjector(modulesToLoad) {
|
|
13517
13552
|
var INSTANTIATING = {},
|
13518
13553
|
providerSuffix = 'Provider',
|
13519
13554
|
path = [],
|
13520
|
-
loadedModules = new HashMap(),
|
13555
|
+
loadedModules = new HashMap([], true),
|
13521
13556
|
providerCache = {
|
13522
13557
|
$provide: {
|
13523
13558
|
provider: supportObject(provider),
|
@@ -13688,8 +13723,7 @@ function createInjector(modulesToLoad) {
|
|
13688
13723
|
: getService(key)
|
13689
13724
|
);
|
13690
13725
|
}
|
13691
|
-
if (
|
13692
|
-
// this means that we must be an array.
|
13726
|
+
if (isArray(fn)) {
|
13693
13727
|
fn = fn[length];
|
13694
13728
|
}
|
13695
13729
|
|
@@ -15022,7 +15056,7 @@ function $TemplateCacheProvider() {
|
|
15022
15056
|
* local name. Given `<widget my-attr="count = count + value">` and widget definition of
|
15023
15057
|
* `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
|
15024
15058
|
* a function wrapper for the `count = count + value` expression. Often it's desirable to
|
15025
|
-
* pass data from the isolated scope via an expression
|
15059
|
+
* pass data from the isolated scope via an expression to the parent scope, this can be
|
15026
15060
|
* done by passing a map of local variable names and values into the expression wrapper fn.
|
15027
15061
|
* For example, if the expression is `increment(amount)` then we can specify the amount value
|
15028
15062
|
* by calling the `localFn` as `localFn({amount: 22})`.
|
@@ -15073,14 +15107,16 @@ function $TemplateCacheProvider() {
|
|
15073
15107
|
*
|
15074
15108
|
*
|
15075
15109
|
* #### `template`
|
15076
|
-
*
|
15077
|
-
*
|
15078
|
-
*
|
15079
|
-
*
|
15110
|
+
* HTML markup that may:
|
15111
|
+
* * Replace the contents of the directive's element (defualt).
|
15112
|
+
* * Replace the directive's element itself (if `replace` is true - DEPRECATED).
|
15113
|
+
* * Wrap the contents of the directive's element (if `transclude` is true).
|
15080
15114
|
*
|
15081
|
-
*
|
15082
|
-
*
|
15083
|
-
*
|
15115
|
+
* Value may be:
|
15116
|
+
*
|
15117
|
+
* * A string. For example `<div red-on-hover>{{delete_str}}</div>`.
|
15118
|
+
* * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`
|
15119
|
+
* function api below) and returns a string value.
|
15084
15120
|
*
|
15085
15121
|
*
|
15086
15122
|
* #### `templateUrl`
|
@@ -15095,11 +15131,14 @@ function $TemplateCacheProvider() {
|
|
15095
15131
|
*
|
15096
15132
|
*
|
15097
15133
|
* #### `replace` ([*DEPRECATED*!], will be removed in next major release)
|
15098
|
-
* specify
|
15134
|
+
* specify what the template should replace. Defaults to `false`.
|
15099
15135
|
*
|
15100
|
-
* * `true` - the template will replace the
|
15101
|
-
* * `false` - the template will replace the contents of the
|
15136
|
+
* * `true` - the template will replace the directive's element.
|
15137
|
+
* * `false` - the template will replace the contents of the directive's element.
|
15102
15138
|
*
|
15139
|
+
* The replacement process migrates all of the attributes / classes from the old element to the new
|
15140
|
+
* one. See the {@link guide/directive#creating-custom-directives_creating-directives_template-expanding-directive
|
15141
|
+
* Directives Guide} for an example.
|
15103
15142
|
*
|
15104
15143
|
* #### `transclude`
|
15105
15144
|
* compile the content of the element and make it available to the directive.
|
@@ -15113,6 +15152,11 @@ function $TemplateCacheProvider() {
|
|
15113
15152
|
* * `true` - transclude the content of the directive.
|
15114
15153
|
* * `'element'` - transclude the whole element including any directives defined at lower priority.
|
15115
15154
|
*
|
15155
|
+
* <div class="alert alert-warning">
|
15156
|
+
* **Note:** When testing an element transclude directive you must not place the directive at the root of the
|
15157
|
+
* DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives
|
15158
|
+
* Testing Transclusion Directives}.
|
15159
|
+
* </div>
|
15116
15160
|
*
|
15117
15161
|
* #### `compile`
|
15118
15162
|
*
|
@@ -15249,10 +15293,10 @@ function $TemplateCacheProvider() {
|
|
15249
15293
|
* to illustrate how `$compile` works.
|
15250
15294
|
* </div>
|
15251
15295
|
*
|
15252
|
-
<example module="
|
15296
|
+
<example module="compileExample">
|
15253
15297
|
<file name="index.html">
|
15254
15298
|
<script>
|
15255
|
-
angular.module('
|
15299
|
+
angular.module('compileExample', [], function($compileProvider) {
|
15256
15300
|
// configure new 'compile' directive by passing a directive
|
15257
15301
|
// factory function. The factory function injects the '$compile'
|
15258
15302
|
$compileProvider.directive('compile', function($compile) {
|
@@ -15276,15 +15320,14 @@ function $TemplateCacheProvider() {
|
|
15276
15320
|
}
|
15277
15321
|
);
|
15278
15322
|
};
|
15279
|
-
})
|
15280
|
-
})
|
15281
|
-
|
15282
|
-
function Ctrl($scope) {
|
15323
|
+
});
|
15324
|
+
})
|
15325
|
+
.controller('GreeterController', ['$scope', function($scope) {
|
15283
15326
|
$scope.name = 'Angular';
|
15284
15327
|
$scope.html = 'Hello {{name}}';
|
15285
|
-
}
|
15328
|
+
}]);
|
15286
15329
|
</script>
|
15287
|
-
<div ng-controller="
|
15330
|
+
<div ng-controller="GreeterController">
|
15288
15331
|
<input ng-model="name"> <br>
|
15289
15332
|
<textarea ng-model="html"></textarea> <br>
|
15290
15333
|
<div compile="html"></div>
|
@@ -15759,7 +15802,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
15759
15802
|
: null;
|
15760
15803
|
|
15761
15804
|
if (nodeLinkFn && nodeLinkFn.scope) {
|
15762
|
-
safeAddClass(
|
15805
|
+
safeAddClass(attrs.$$element, 'ng-scope');
|
15763
15806
|
}
|
15764
15807
|
|
15765
15808
|
childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||
|
@@ -15781,7 +15824,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
15781
15824
|
return linkFnFound ? compositeLinkFn : null;
|
15782
15825
|
|
15783
15826
|
function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {
|
15784
|
-
var nodeLinkFn, childLinkFn, node,
|
15827
|
+
var nodeLinkFn, childLinkFn, node, childScope, i, ii, n, childBoundTranscludeFn;
|
15785
15828
|
|
15786
15829
|
// copy nodeList so that linking doesn't break due to live list updates.
|
15787
15830
|
var nodeListLength = nodeList.length,
|
@@ -15794,12 +15837,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
15794
15837
|
node = stableNodeList[n];
|
15795
15838
|
nodeLinkFn = linkFns[i++];
|
15796
15839
|
childLinkFn = linkFns[i++];
|
15797
|
-
$node = jqLite(node);
|
15798
15840
|
|
15799
15841
|
if (nodeLinkFn) {
|
15800
15842
|
if (nodeLinkFn.scope) {
|
15801
15843
|
childScope = scope.$new();
|
15802
|
-
|
15844
|
+
jqLite.data(node, '$scope', childScope);
|
15803
15845
|
} else {
|
15804
15846
|
childScope = scope;
|
15805
15847
|
}
|
@@ -15870,7 +15912,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
15870
15912
|
directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority, ignoreDirective);
|
15871
15913
|
|
15872
15914
|
// iterate over the attributes
|
15873
|
-
for (var attr, name, nName, ngAttrName, value, nAttrs = node.attributes,
|
15915
|
+
for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
|
15874
15916
|
j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
|
15875
15917
|
var attrStartName = false;
|
15876
15918
|
var attrEndName = false;
|
@@ -15878,9 +15920,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
15878
15920
|
attr = nAttrs[j];
|
15879
15921
|
if (!msie || msie >= 8 || attr.specified) {
|
15880
15922
|
name = attr.name;
|
15923
|
+
value = trim(attr.value);
|
15924
|
+
|
15881
15925
|
// support ngAttr attribute binding
|
15882
15926
|
ngAttrName = directiveNormalize(name);
|
15883
|
-
if (NG_ATTR_BINDING.test(ngAttrName)) {
|
15927
|
+
if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
|
15884
15928
|
name = snake_case(ngAttrName.substr(6), '-');
|
15885
15929
|
}
|
15886
15930
|
|
@@ -15893,9 +15937,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
15893
15937
|
|
15894
15938
|
nName = directiveNormalize(name.toLowerCase());
|
15895
15939
|
attrsMap[nName] = name;
|
15896
|
-
|
15897
|
-
|
15898
|
-
|
15940
|
+
if (isNgAttr || !attrs.hasOwnProperty(nName)) {
|
15941
|
+
attrs[nName] = value;
|
15942
|
+
if (getBooleanAttrName(node, nName)) {
|
15943
|
+
attrs[nName] = true; // presence means true
|
15944
|
+
}
|
15899
15945
|
}
|
15900
15946
|
addAttrInterpolateDirective(node, directives, value, nName);
|
15901
15947
|
addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
|
@@ -16087,12 +16133,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
16087
16133
|
if (directiveValue == 'element') {
|
16088
16134
|
hasElementTranscludeDirective = true;
|
16089
16135
|
terminalPriority = directive.priority;
|
16090
|
-
$template =
|
16136
|
+
$template = $compileNode;
|
16091
16137
|
$compileNode = templateAttrs.$$element =
|
16092
16138
|
jqLite(document.createComment(' ' + directiveName + ': ' +
|
16093
16139
|
templateAttrs[directiveName] + ' '));
|
16094
16140
|
compileNode = $compileNode[0];
|
16095
|
-
replaceWith(jqCollection,
|
16141
|
+
replaceWith(jqCollection, sliceArgs($template), compileNode);
|
16096
16142
|
|
16097
16143
|
childTranscludeFn = compile($template, transcludeFn, terminalPriority,
|
16098
16144
|
replaceDirective && replaceDirective.name, {
|
@@ -16269,29 +16315,26 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
16269
16315
|
function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
|
16270
16316
|
var attrs, $element, i, ii, linkFn, controller, isolateScope, elementControllers = {}, transcludeFn;
|
16271
16317
|
|
16272
|
-
|
16273
|
-
|
16274
|
-
|
16275
|
-
attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));
|
16276
|
-
}
|
16318
|
+
attrs = (compileNode === linkNode)
|
16319
|
+
? templateAttrs
|
16320
|
+
: shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));
|
16277
16321
|
$element = attrs.$$element;
|
16278
16322
|
|
16279
16323
|
if (newIsolateScopeDirective) {
|
16280
16324
|
var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;
|
16281
|
-
var $linkNode = jqLite(linkNode);
|
16282
16325
|
|
16283
16326
|
isolateScope = scope.$new(true);
|
16284
16327
|
|
16285
16328
|
if (templateDirective && (templateDirective === newIsolateScopeDirective ||
|
16286
16329
|
templateDirective === newIsolateScopeDirective.$$originalDirective)) {
|
16287
|
-
$
|
16330
|
+
$element.data('$isolateScope', isolateScope);
|
16288
16331
|
} else {
|
16289
|
-
$
|
16332
|
+
$element.data('$isolateScopeNoTemplate', isolateScope);
|
16290
16333
|
}
|
16291
16334
|
|
16292
16335
|
|
16293
16336
|
|
16294
|
-
safeAddClass($
|
16337
|
+
safeAddClass($element, 'ng-isolate-scope');
|
16295
16338
|
|
16296
16339
|
forEach(newIsolateScopeDirective.scope, function(definition, scopeName) {
|
16297
16340
|
var match = definition.match(LOCAL_REGEXP) || [],
|
@@ -16993,7 +17036,7 @@ function $ControllerProvider() {
|
|
16993
17036
|
instance = $injector.instantiate(expression, locals);
|
16994
17037
|
|
16995
17038
|
if (identifier) {
|
16996
|
-
if (!(locals && typeof locals.$scope
|
17039
|
+
if (!(locals && typeof locals.$scope === 'object')) {
|
16997
17040
|
throw minErr('$controller')('noscp',
|
16998
17041
|
"Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
|
16999
17042
|
constructor || expression.name, identifier);
|
@@ -17016,18 +17059,19 @@ function $ControllerProvider() {
|
|
17016
17059
|
* A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.
|
17017
17060
|
*
|
17018
17061
|
* @example
|
17019
|
-
<example>
|
17062
|
+
<example module="documentExample">
|
17020
17063
|
<file name="index.html">
|
17021
|
-
<div ng-controller="
|
17064
|
+
<div ng-controller="ExampleController">
|
17022
17065
|
<p>$document title: <b ng-bind="title"></b></p>
|
17023
17066
|
<p>window.document title: <b ng-bind="windowTitle"></b></p>
|
17024
17067
|
</div>
|
17025
17068
|
</file>
|
17026
17069
|
<file name="script.js">
|
17027
|
-
|
17028
|
-
$scope
|
17029
|
-
|
17030
|
-
|
17070
|
+
angular.module('documentExample', [])
|
17071
|
+
.controller('ExampleController', ['$scope', '$document', function($scope, $document) {
|
17072
|
+
$scope.title = $document[0].title;
|
17073
|
+
$scope.windowTitle = angular.element(window.document)[0].title;
|
17074
|
+
}]);
|
17031
17075
|
</file>
|
17032
17076
|
</example>
|
17033
17077
|
*/
|
@@ -17094,11 +17138,7 @@ function parseHeaders(headers) {
|
|
17094
17138
|
val = trim(line.substr(i + 1));
|
17095
17139
|
|
17096
17140
|
if (key) {
|
17097
|
-
|
17098
|
-
parsed[key] += ', ' + val;
|
17099
|
-
} else {
|
17100
|
-
parsed[key] = val;
|
17101
|
-
}
|
17141
|
+
parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
|
17102
17142
|
}
|
17103
17143
|
});
|
17104
17144
|
|
@@ -17160,12 +17200,39 @@ function isSuccess(status) {
|
|
17160
17200
|
}
|
17161
17201
|
|
17162
17202
|
|
17203
|
+
/**
|
17204
|
+
* @ngdoc provider
|
17205
|
+
* @name $httpProvider
|
17206
|
+
* @description
|
17207
|
+
* Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
|
17208
|
+
* */
|
17163
17209
|
function $HttpProvider() {
|
17164
17210
|
var JSON_START = /^\s*(\[|\{[^\{])/,
|
17165
17211
|
JSON_END = /[\}\]]\s*$/,
|
17166
17212
|
PROTECTION_PREFIX = /^\)\]\}',?\n/,
|
17167
17213
|
CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': 'application/json;charset=utf-8'};
|
17168
17214
|
|
17215
|
+
/**
|
17216
|
+
* @ngdoc property
|
17217
|
+
* @name $httpProvider#defaults
|
17218
|
+
* @description
|
17219
|
+
*
|
17220
|
+
* Object containing default values for all {@link ng.$http $http} requests.
|
17221
|
+
*
|
17222
|
+
* - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
|
17223
|
+
* Defaults value is `'XSRF-TOKEN'`.
|
17224
|
+
*
|
17225
|
+
* - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
|
17226
|
+
* XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
|
17227
|
+
*
|
17228
|
+
* - **`defaults.headers`** - {Object} - Default headers for all $http requests.
|
17229
|
+
* Refer to {@link ng.$http#setting-http-headers $http} for documentation on
|
17230
|
+
* setting default headers.
|
17231
|
+
* - **`defaults.headers.common`**
|
17232
|
+
* - **`defaults.headers.post`**
|
17233
|
+
* - **`defaults.headers.put`**
|
17234
|
+
* - **`defaults.headers.patch`**
|
17235
|
+
**/
|
17169
17236
|
var defaults = this.defaults = {
|
17170
17237
|
// transform incoming response data
|
17171
17238
|
transformResponse: [function(data) {
|
@@ -17655,9 +17722,9 @@ function $HttpProvider() {
|
|
17655
17722
|
*
|
17656
17723
|
*
|
17657
17724
|
* @example
|
17658
|
-
<example>
|
17725
|
+
<example module="httpExample">
|
17659
17726
|
<file name="index.html">
|
17660
|
-
<div ng-controller="
|
17727
|
+
<div ng-controller="FetchController">
|
17661
17728
|
<select ng-model="method">
|
17662
17729
|
<option>GET</option>
|
17663
17730
|
<option>JSONP</option>
|
@@ -17679,30 +17746,32 @@ function $HttpProvider() {
|
|
17679
17746
|
</div>
|
17680
17747
|
</file>
|
17681
17748
|
<file name="script.js">
|
17682
|
-
|
17683
|
-
$scope
|
17684
|
-
|
17685
|
-
|
17686
|
-
|
17687
|
-
|
17688
|
-
|
17689
|
-
|
17690
|
-
|
17691
|
-
|
17692
|
-
$scope.
|
17693
|
-
|
17694
|
-
|
17695
|
-
|
17696
|
-
|
17697
|
-
|
17698
|
-
|
17699
|
-
|
17749
|
+
angular.module('httpExample', [])
|
17750
|
+
.controller('FetchController', ['$scope', '$http', '$templateCache',
|
17751
|
+
function($scope, $http, $templateCache) {
|
17752
|
+
$scope.method = 'GET';
|
17753
|
+
$scope.url = 'http-hello.html';
|
17754
|
+
|
17755
|
+
$scope.fetch = function() {
|
17756
|
+
$scope.code = null;
|
17757
|
+
$scope.response = null;
|
17758
|
+
|
17759
|
+
$http({method: $scope.method, url: $scope.url, cache: $templateCache}).
|
17760
|
+
success(function(data, status) {
|
17761
|
+
$scope.status = status;
|
17762
|
+
$scope.data = data;
|
17763
|
+
}).
|
17764
|
+
error(function(data, status) {
|
17765
|
+
$scope.data = data || "Request failed";
|
17766
|
+
$scope.status = status;
|
17767
|
+
});
|
17768
|
+
};
|
17700
17769
|
|
17701
|
-
|
17702
|
-
|
17703
|
-
|
17704
|
-
|
17705
|
-
|
17770
|
+
$scope.updateModel = function(method, url) {
|
17771
|
+
$scope.method = method;
|
17772
|
+
$scope.url = url;
|
17773
|
+
};
|
17774
|
+
}]);
|
17706
17775
|
</file>
|
17707
17776
|
<file name="http-hello.html">
|
17708
17777
|
Hello, $http!
|
@@ -17756,7 +17825,7 @@ function $HttpProvider() {
|
|
17756
17825
|
var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);
|
17757
17826
|
|
17758
17827
|
// strip content-type if data is undefined
|
17759
|
-
if (isUndefined(
|
17828
|
+
if (isUndefined(reqData)) {
|
17760
17829
|
forEach(headers, function(value, header) {
|
17761
17830
|
if (lowercase(header) === 'content-type') {
|
17762
17831
|
delete headers[header];
|
@@ -17825,10 +17894,6 @@ function $HttpProvider() {
|
|
17825
17894
|
|
17826
17895
|
defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
|
17827
17896
|
|
17828
|
-
// execute if header value is function
|
17829
|
-
execHeaders(defHeaders);
|
17830
|
-
execHeaders(reqHeaders);
|
17831
|
-
|
17832
17897
|
// using for-in instead of forEach to avoid unecessary iteration after header has been found
|
17833
17898
|
defaultHeadersIteration:
|
17834
17899
|
for (defHeaderName in defHeaders) {
|
@@ -17843,6 +17908,8 @@ function $HttpProvider() {
|
|
17843
17908
|
reqHeaders[defHeaderName] = defHeaders[defHeaderName];
|
17844
17909
|
}
|
17845
17910
|
|
17911
|
+
// execute if header value is a function for merged headers
|
17912
|
+
execHeaders(reqHeaders);
|
17846
17913
|
return reqHeaders;
|
17847
17914
|
|
17848
17915
|
function execHeaders(headers) {
|
@@ -17908,7 +17975,7 @@ function $HttpProvider() {
|
|
17908
17975
|
* Shortcut method to perform `JSONP` request.
|
17909
17976
|
*
|
17910
17977
|
* @param {string} url Relative or absolute URL specifying the destination of the request.
|
17911
|
-
*
|
17978
|
+
* The name of the callback should be the string `JSON_CALLBACK`.
|
17912
17979
|
* @param {Object=} config Optional configuration object
|
17913
17980
|
* @returns {HttpPromise} Future object
|
17914
17981
|
*/
|
@@ -18008,7 +18075,7 @@ function $HttpProvider() {
|
|
18008
18075
|
if (cache) {
|
18009
18076
|
cachedResp = cache.get(url);
|
18010
18077
|
if (isDefined(cachedResp)) {
|
18011
|
-
if (cachedResp
|
18078
|
+
if (isPromiseLike(cachedResp)) {
|
18012
18079
|
// cached request has already been sent, but there is no response yet
|
18013
18080
|
cachedResp.then(removePendingReq, removePendingReq);
|
18014
18081
|
return cachedResp;
|
@@ -18090,27 +18157,29 @@ function $HttpProvider() {
|
|
18090
18157
|
|
18091
18158
|
|
18092
18159
|
function buildUrl(url, params) {
|
18093
|
-
|
18094
|
-
|
18095
|
-
|
18096
|
-
|
18097
|
-
|
18098
|
-
|
18099
|
-
|
18100
|
-
|
18101
|
-
|
18102
|
-
|
18103
|
-
|
18104
|
-
|
18105
|
-
}
|
18106
|
-
});
|
18107
|
-
if(parts.length > 0) {
|
18108
|
-
url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
|
18160
|
+
if (!params) return url;
|
18161
|
+
var parts = [];
|
18162
|
+
forEachSorted(params, function(value, key) {
|
18163
|
+
if (value === null || isUndefined(value)) return;
|
18164
|
+
if (!isArray(value)) value = [value];
|
18165
|
+
|
18166
|
+
forEach(value, function(v) {
|
18167
|
+
if (isObject(v)) {
|
18168
|
+
if (isDate(v)){
|
18169
|
+
v = v.toISOString();
|
18170
|
+
} else if (isObject(v)) {
|
18171
|
+
v = toJson(v);
|
18172
|
+
}
|
18109
18173
|
}
|
18110
|
-
|
18111
|
-
|
18112
|
-
|
18113
|
-
|
18174
|
+
parts.push(encodeUriQuery(key) + '=' +
|
18175
|
+
encodeUriQuery(v));
|
18176
|
+
});
|
18177
|
+
});
|
18178
|
+
if(parts.length > 0) {
|
18179
|
+
url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
|
18180
|
+
}
|
18181
|
+
return url;
|
18182
|
+
}
|
18114
18183
|
}];
|
18115
18184
|
}
|
18116
18185
|
|
@@ -18195,7 +18264,8 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
|
|
18195
18264
|
// Safari respectively.
|
18196
18265
|
if (xhr && xhr.readyState == 4) {
|
18197
18266
|
var responseHeaders = null,
|
18198
|
-
response = null
|
18267
|
+
response = null,
|
18268
|
+
statusText = '';
|
18199
18269
|
|
18200
18270
|
if(status !== ABORTED) {
|
18201
18271
|
responseHeaders = xhr.getAllResponseHeaders();
|
@@ -18205,11 +18275,17 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
|
|
18205
18275
|
response = ('response' in xhr) ? xhr.response : xhr.responseText;
|
18206
18276
|
}
|
18207
18277
|
|
18278
|
+
// Accessing statusText on an aborted xhr object will
|
18279
|
+
// throw an 'c00c023f error' in IE9 and lower, don't touch it.
|
18280
|
+
if (!(status === ABORTED && msie < 10)) {
|
18281
|
+
statusText = xhr.statusText;
|
18282
|
+
}
|
18283
|
+
|
18208
18284
|
completeRequest(callback,
|
18209
18285
|
status || xhr.status,
|
18210
18286
|
response,
|
18211
18287
|
responseHeaders,
|
18212
|
-
|
18288
|
+
statusText);
|
18213
18289
|
}
|
18214
18290
|
};
|
18215
18291
|
|
@@ -18239,7 +18315,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
|
|
18239
18315
|
|
18240
18316
|
if (timeout > 0) {
|
18241
18317
|
var timeoutId = $browserDefer(timeoutRequest, timeout);
|
18242
|
-
} else if (timeout
|
18318
|
+
} else if (isPromiseLike(timeout)) {
|
18243
18319
|
timeout.then(timeoutRequest);
|
18244
18320
|
}
|
18245
18321
|
|
@@ -18611,25 +18687,27 @@ function $IntervalProvider() {
|
|
18611
18687
|
* @returns {promise} A promise which will be notified on each iteration.
|
18612
18688
|
*
|
18613
18689
|
* @example
|
18614
|
-
* <example module="
|
18615
|
-
*
|
18616
|
-
*
|
18617
|
-
*
|
18618
|
-
*
|
18619
|
-
* $scope
|
18620
|
-
*
|
18690
|
+
* <example module="intervalExample">
|
18691
|
+
* <file name="index.html">
|
18692
|
+
* <script>
|
18693
|
+
* angular.module('intervalExample', [])
|
18694
|
+
* .controller('ExampleController', ['$scope', '$interval',
|
18695
|
+
* function($scope, $interval) {
|
18696
|
+
* $scope.format = 'M/d/yy h:mm:ss a';
|
18697
|
+
* $scope.blood_1 = 100;
|
18698
|
+
* $scope.blood_2 = 120;
|
18621
18699
|
*
|
18622
|
-
*
|
18623
|
-
*
|
18624
|
-
*
|
18625
|
-
*
|
18700
|
+
* var stop;
|
18701
|
+
* $scope.fight = function() {
|
18702
|
+
* // Don't start a new fight if we are already fighting
|
18703
|
+
* if ( angular.isDefined(stop) ) return;
|
18626
18704
|
*
|
18627
18705
|
* stop = $interval(function() {
|
18628
18706
|
* if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
|
18629
|
-
*
|
18630
|
-
*
|
18707
|
+
* $scope.blood_1 = $scope.blood_1 - 3;
|
18708
|
+
* $scope.blood_2 = $scope.blood_2 - 4;
|
18631
18709
|
* } else {
|
18632
|
-
*
|
18710
|
+
* $scope.stopFight();
|
18633
18711
|
* }
|
18634
18712
|
* }, 100);
|
18635
18713
|
* };
|
@@ -18644,22 +18722,21 @@ function $IntervalProvider() {
|
|
18644
18722
|
* $scope.resetFight = function() {
|
18645
18723
|
* $scope.blood_1 = 100;
|
18646
18724
|
* $scope.blood_2 = 120;
|
18647
|
-
* }
|
18725
|
+
* };
|
18648
18726
|
*
|
18649
18727
|
* $scope.$on('$destroy', function() {
|
18650
|
-
* // Make sure that the interval
|
18728
|
+
* // Make sure that the interval nis destroyed too
|
18651
18729
|
* $scope.stopFight();
|
18652
18730
|
* });
|
18653
|
-
* }
|
18654
|
-
*
|
18655
|
-
*
|
18656
|
-
*
|
18657
|
-
*
|
18658
|
-
* .directive('myCurrentTime', function($interval, dateFilter) {
|
18731
|
+
* }])
|
18732
|
+
* // Register the 'myCurrentTime' directive factory method.
|
18733
|
+
* // We inject $interval and dateFilter service since the factory method is DI.
|
18734
|
+
* .directive('myCurrentTime', ['$interval', 'dateFilter',
|
18735
|
+
* function($interval, dateFilter) {
|
18659
18736
|
* // return the directive link function. (compile function not needed)
|
18660
18737
|
* return function(scope, element, attrs) {
|
18661
18738
|
* var format, // date format
|
18662
|
-
*
|
18739
|
+
* stopTime; // so that we can cancel the time updates
|
18663
18740
|
*
|
18664
18741
|
* // used to update the UI
|
18665
18742
|
* function updateTime() {
|
@@ -18675,28 +18752,28 @@ function $IntervalProvider() {
|
|
18675
18752
|
* stopTime = $interval(updateTime, 1000);
|
18676
18753
|
*
|
18677
18754
|
* // listen on DOM destroy (removal) event, and cancel the next UI update
|
18678
|
-
* // to prevent updating time
|
18755
|
+
* // to prevent updating time after the DOM element was removed.
|
18679
18756
|
* element.bind('$destroy', function() {
|
18680
18757
|
* $interval.cancel(stopTime);
|
18681
18758
|
* });
|
18682
18759
|
* }
|
18683
|
-
* });
|
18684
|
-
*
|
18760
|
+
* }]);
|
18761
|
+
* </script>
|
18685
18762
|
*
|
18686
|
-
*
|
18687
|
-
*
|
18688
|
-
*
|
18689
|
-
*
|
18690
|
-
*
|
18691
|
-
*
|
18692
|
-
*
|
18693
|
-
*
|
18694
|
-
*
|
18695
|
-
*
|
18696
|
-
* </div>
|
18763
|
+
* <div>
|
18764
|
+
* <div ng-controller="ExampleController">
|
18765
|
+
* Date format: <input ng-model="format"> <hr/>
|
18766
|
+
* Current time is: <span my-current-time="format"></span>
|
18767
|
+
* <hr/>
|
18768
|
+
* Blood 1 : <font color='red'>{{blood_1}}</font>
|
18769
|
+
* Blood 2 : <font color='red'>{{blood_2}}</font>
|
18770
|
+
* <button type="button" data-ng-click="fight()">Fight</button>
|
18771
|
+
* <button type="button" data-ng-click="stopFight()">StopFight</button>
|
18772
|
+
* <button type="button" data-ng-click="resetFight()">resetFight</button>
|
18697
18773
|
* </div>
|
18774
|
+
* </div>
|
18698
18775
|
*
|
18699
|
-
*
|
18776
|
+
* </file>
|
18700
18777
|
* </example>
|
18701
18778
|
*/
|
18702
18779
|
function interval(fn, delay, count, invokeApply) {
|
@@ -18743,7 +18820,7 @@ function $IntervalProvider() {
|
|
18743
18820
|
interval.cancel = function(promise) {
|
18744
18821
|
if (promise && promise.$$intervalId in intervals) {
|
18745
18822
|
intervals[promise.$$intervalId].reject('canceled');
|
18746
|
-
clearInterval(promise.$$intervalId);
|
18823
|
+
$window.clearInterval(promise.$$intervalId);
|
18747
18824
|
delete intervals[promise.$$intervalId];
|
18748
18825
|
return true;
|
18749
18826
|
}
|
@@ -19253,14 +19330,17 @@ LocationHashbangInHtml5Url.prototype =
|
|
19253
19330
|
* If the argument is a hash object containing an array of values, these values will be encoded
|
19254
19331
|
* as duplicate search parameters in the url.
|
19255
19332
|
*
|
19256
|
-
* @param {(string|Array<string
|
19257
|
-
* override only a single search property.
|
19333
|
+
* @param {(string|Array<string>|boolean)=} paramValue If `search` is a string, then `paramValue`
|
19334
|
+
* will override only a single search property.
|
19258
19335
|
*
|
19259
19336
|
* If `paramValue` is an array, it will override the property of the `search` component of
|
19260
19337
|
* `$location` specified via the first argument.
|
19261
19338
|
*
|
19262
19339
|
* If `paramValue` is `null`, the property specified via the first argument will be deleted.
|
19263
19340
|
*
|
19341
|
+
* If `paramValue` is `true`, the property specified via the first argument will be added with no
|
19342
|
+
* value nor trailing equal sign.
|
19343
|
+
*
|
19264
19344
|
* @return {Object} If called with no arguments returns the parsed `search` object. If called with
|
19265
19345
|
* one or more arguments returns `$location` object itself.
|
19266
19346
|
*/
|
@@ -19272,6 +19352,11 @@ LocationHashbangInHtml5Url.prototype =
|
|
19272
19352
|
if (isString(search)) {
|
19273
19353
|
this.$$search = parseKeyValue(search);
|
19274
19354
|
} else if (isObject(search)) {
|
19355
|
+
// remove object undefined or null properties
|
19356
|
+
forEach(search, function(value, key) {
|
19357
|
+
if (value == null) delete search[key];
|
19358
|
+
});
|
19359
|
+
|
19275
19360
|
this.$$search = search;
|
19276
19361
|
} else {
|
19277
19362
|
throw $locationMinErr('isrcharg',
|
@@ -19377,7 +19462,7 @@ function $LocationProvider(){
|
|
19377
19462
|
html5Mode = false;
|
19378
19463
|
|
19379
19464
|
/**
|
19380
|
-
* @ngdoc
|
19465
|
+
* @ngdoc method
|
19381
19466
|
* @name $locationProvider#hashPrefix
|
19382
19467
|
* @description
|
19383
19468
|
* @param {string=} prefix Prefix for hash part (containing path and search)
|
@@ -19393,7 +19478,7 @@ function $LocationProvider(){
|
|
19393
19478
|
};
|
19394
19479
|
|
19395
19480
|
/**
|
19396
|
-
* @ngdoc
|
19481
|
+
* @ngdoc method
|
19397
19482
|
* @name $locationProvider#html5Mode
|
19398
19483
|
* @description
|
19399
19484
|
* @param {boolean=} mode Use HTML5 strategy if available.
|
@@ -19593,15 +19678,16 @@ function $LocationProvider(){
|
|
19593
19678
|
* {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.
|
19594
19679
|
*
|
19595
19680
|
* @example
|
19596
|
-
<example>
|
19681
|
+
<example module="logExample">
|
19597
19682
|
<file name="script.js">
|
19598
|
-
|
19599
|
-
$scope
|
19600
|
-
|
19601
|
-
|
19683
|
+
angular.module('logExample', [])
|
19684
|
+
.controller('LogController', ['$scope', '$log', function($scope, $log) {
|
19685
|
+
$scope.$log = $log;
|
19686
|
+
$scope.message = 'Hello World!';
|
19687
|
+
}]);
|
19602
19688
|
</file>
|
19603
19689
|
<file name="index.html">
|
19604
|
-
<div ng-controller="
|
19690
|
+
<div ng-controller="LogController">
|
19605
19691
|
<p>Reload this page with open console, enter text and hit the log button...</p>
|
19606
19692
|
Message:
|
19607
19693
|
<input type="text" ng-model="message"/>
|
@@ -19625,7 +19711,7 @@ function $LogProvider(){
|
|
19625
19711
|
self = this;
|
19626
19712
|
|
19627
19713
|
/**
|
19628
|
-
* @ngdoc
|
19714
|
+
* @ngdoc method
|
19629
19715
|
* @name $logProvider#debugEnabled
|
19630
19716
|
* @description
|
19631
19717
|
* @param {boolean=} flag enable or disable debug level messages
|
@@ -19751,14 +19837,7 @@ var promiseWarning;
|
|
19751
19837
|
//
|
19752
19838
|
// As an example, consider the following Angular expression:
|
19753
19839
|
//
|
19754
|
-
// {}.toString.constructor(alert("evil JS code"))
|
19755
|
-
//
|
19756
|
-
// We want to prevent this type of access. For the sake of performance, during the lexing phase we
|
19757
|
-
// disallow any "dotted" access to any member named "constructor".
|
19758
|
-
//
|
19759
|
-
// For reflective calls (a[b]) we check that the value of the lookup is not the Function constructor
|
19760
|
-
// while evaluating the expression, which is a stronger but more expensive test. Since reflective
|
19761
|
-
// calls are expensive anyway, this is not such a big deal compared to static dereferencing.
|
19840
|
+
// {}.toString.constructor('alert("evil JS code")')
|
19762
19841
|
//
|
19763
19842
|
// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
|
19764
19843
|
// against the expression language, but not to prevent exploits that were enabled by exposing
|
@@ -19766,17 +19845,19 @@ var promiseWarning;
|
|
19766
19845
|
// practice and therefore we are not even trying to protect against interaction with an object
|
19767
19846
|
// explicitly exposed in this way.
|
19768
19847
|
//
|
19769
|
-
// A developer could foil the name check by aliasing the Function constructor under a different
|
19770
|
-
// name on the scope.
|
19771
|
-
//
|
19772
19848
|
// In general, it is not possible to access a Window object from an angular expression unless a
|
19773
19849
|
// window or some DOM object that has a reference to window is published onto a Scope.
|
19850
|
+
// Similarly we prevent invocations of function known to be dangerous, as well as assignments to
|
19851
|
+
// native objects.
|
19852
|
+
|
19774
19853
|
|
19775
19854
|
function ensureSafeMemberName(name, fullExpression) {
|
19776
|
-
if (name === "
|
19855
|
+
if (name === "__defineGetter__" || name === "__defineSetter__"
|
19856
|
+
|| name === "__lookupGetter__" || name === "__lookupSetter__"
|
19857
|
+
|| name === "__proto__") {
|
19777
19858
|
throw $parseMinErr('isecfld',
|
19778
|
-
'
|
19779
|
-
fullExpression);
|
19859
|
+
'Attempting to access a disallowed field in Angular expressions! '
|
19860
|
+
+'Expression: {0}', fullExpression);
|
19780
19861
|
}
|
19781
19862
|
return name;
|
19782
19863
|
}
|
@@ -19798,11 +19879,34 @@ function ensureSafeObject(obj, fullExpression) {
|
|
19798
19879
|
throw $parseMinErr('isecdom',
|
19799
19880
|
'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
|
19800
19881
|
fullExpression);
|
19882
|
+
} else if (// block Object so that we can't get hold of dangerous Object.* methods
|
19883
|
+
obj === Object) {
|
19884
|
+
throw $parseMinErr('isecobj',
|
19885
|
+
'Referencing Object in Angular expressions is disallowed! Expression: {0}',
|
19886
|
+
fullExpression);
|
19801
19887
|
}
|
19802
19888
|
}
|
19803
19889
|
return obj;
|
19804
19890
|
}
|
19805
19891
|
|
19892
|
+
var CALL = Function.prototype.call;
|
19893
|
+
var APPLY = Function.prototype.apply;
|
19894
|
+
var BIND = Function.prototype.bind;
|
19895
|
+
|
19896
|
+
function ensureSafeFunction(obj, fullExpression) {
|
19897
|
+
if (obj) {
|
19898
|
+
if (obj.constructor === obj) {
|
19899
|
+
throw $parseMinErr('isecfn',
|
19900
|
+
'Referencing Function in Angular expressions is disallowed! Expression: {0}',
|
19901
|
+
fullExpression);
|
19902
|
+
} else if (obj === CALL || obj === APPLY || (BIND && obj === BIND)) {
|
19903
|
+
throw $parseMinErr('isecff',
|
19904
|
+
'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',
|
19905
|
+
fullExpression);
|
19906
|
+
}
|
19907
|
+
}
|
19908
|
+
}
|
19909
|
+
|
19806
19910
|
var OPERATORS = {
|
19807
19911
|
/* jshint bitwise : false */
|
19808
19912
|
'null':function(){return null;},
|
@@ -20082,11 +20186,7 @@ Lexer.prototype = {
|
|
20082
20186
|
string += String.fromCharCode(parseInt(hex, 16));
|
20083
20187
|
} else {
|
20084
20188
|
var rep = ESCAPE[ch];
|
20085
|
-
|
20086
|
-
string += rep;
|
20087
|
-
} else {
|
20088
|
-
string += ch;
|
20089
|
-
}
|
20189
|
+
string = string + (rep || ch);
|
20090
20190
|
}
|
20091
20191
|
escape = false;
|
20092
20192
|
} else if (ch === '\\') {
|
@@ -20437,6 +20537,7 @@ Parser.prototype = {
|
|
20437
20537
|
i = indexFn(self, locals),
|
20438
20538
|
v, p;
|
20439
20539
|
|
20540
|
+
ensureSafeMemberName(i, parser.text);
|
20440
20541
|
if (!o) return undefined;
|
20441
20542
|
v = ensureSafeObject(o[i], parser.text);
|
20442
20543
|
if (v && v.then && parser.options.unwrapPromises) {
|
@@ -20479,7 +20580,7 @@ Parser.prototype = {
|
|
20479
20580
|
var fnPtr = fn(scope, locals, context) || noop;
|
20480
20581
|
|
20481
20582
|
ensureSafeObject(context, parser.text);
|
20482
|
-
|
20583
|
+
ensureSafeFunction(fnPtr, parser.text);
|
20483
20584
|
|
20484
20585
|
// IE stupidity! (IE doesn't have apply for some native functions)
|
20485
20586
|
var v = fnPtr.apply
|
@@ -20588,6 +20689,8 @@ function setter(obj, path, setValue, fullExp, options) {
|
|
20588
20689
|
}
|
20589
20690
|
}
|
20590
20691
|
key = ensureSafeMemberName(element.shift(), fullExp);
|
20692
|
+
ensureSafeObject(obj, fullExp);
|
20693
|
+
ensureSafeObject(obj[key], fullExp);
|
20591
20694
|
obj[key] = setValue;
|
20592
20695
|
return setValue;
|
20593
20696
|
}
|
@@ -20703,26 +20806,6 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
|
|
20703
20806
|
};
|
20704
20807
|
}
|
20705
20808
|
|
20706
|
-
function simpleGetterFn1(key0, fullExp) {
|
20707
|
-
ensureSafeMemberName(key0, fullExp);
|
20708
|
-
|
20709
|
-
return function simpleGetterFn1(scope, locals) {
|
20710
|
-
if (scope == null) return undefined;
|
20711
|
-
return ((locals && locals.hasOwnProperty(key0)) ? locals : scope)[key0];
|
20712
|
-
};
|
20713
|
-
}
|
20714
|
-
|
20715
|
-
function simpleGetterFn2(key0, key1, fullExp) {
|
20716
|
-
ensureSafeMemberName(key0, fullExp);
|
20717
|
-
ensureSafeMemberName(key1, fullExp);
|
20718
|
-
|
20719
|
-
return function simpleGetterFn2(scope, locals) {
|
20720
|
-
if (scope == null) return undefined;
|
20721
|
-
scope = ((locals && locals.hasOwnProperty(key0)) ? locals : scope)[key0];
|
20722
|
-
return scope == null ? undefined : scope[key1];
|
20723
|
-
};
|
20724
|
-
}
|
20725
|
-
|
20726
20809
|
function getterFn(path, options, fullExp) {
|
20727
20810
|
// Check whether the cache has this getter already.
|
20728
20811
|
// We can use hasOwnProperty directly on the cache because we ensure,
|
@@ -20735,13 +20818,8 @@ function getterFn(path, options, fullExp) {
|
|
20735
20818
|
pathKeysLength = pathKeys.length,
|
20736
20819
|
fn;
|
20737
20820
|
|
20738
|
-
// When we have only 1 or 2 tokens, use optimized special case closures.
|
20739
20821
|
// http://jsperf.com/angularjs-parse-getter/6
|
20740
|
-
if (
|
20741
|
-
fn = simpleGetterFn1(pathKeys[0], fullExp);
|
20742
|
-
} else if (!options.unwrapPromises && pathKeysLength === 2) {
|
20743
|
-
fn = simpleGetterFn2(pathKeys[0], pathKeys[1], fullExp);
|
20744
|
-
} else if (options.csp) {
|
20822
|
+
if (options.csp) {
|
20745
20823
|
if (pathKeysLength < 6) {
|
20746
20824
|
fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp,
|
20747
20825
|
options);
|
@@ -21007,17 +21085,13 @@ function $ParseProvider() {
|
|
21007
21085
|
* var deferred = $q.defer();
|
21008
21086
|
*
|
21009
21087
|
* setTimeout(function() {
|
21010
|
-
*
|
21011
|
-
*
|
21012
|
-
*
|
21013
|
-
* deferred.
|
21014
|
-
*
|
21015
|
-
*
|
21016
|
-
*
|
21017
|
-
* } else {
|
21018
|
-
* deferred.reject('Greeting ' + name + ' is not allowed.');
|
21019
|
-
* }
|
21020
|
-
* });
|
21088
|
+
* deferred.notify('About to greet ' + name + '.');
|
21089
|
+
*
|
21090
|
+
* if (okToGreet(name)) {
|
21091
|
+
* deferred.resolve('Hello, ' + name + '!');
|
21092
|
+
* } else {
|
21093
|
+
* deferred.reject('Greeting ' + name + ' is not allowed.');
|
21094
|
+
* }
|
21021
21095
|
* }, 1000);
|
21022
21096
|
*
|
21023
21097
|
* return deferred.promise;
|
@@ -21291,7 +21365,7 @@ function qFactory(nextTick, exceptionHandler) {
|
|
21291
21365
|
} catch(e) {
|
21292
21366
|
return makePromise(e, false);
|
21293
21367
|
}
|
21294
|
-
if (
|
21368
|
+
if (isPromiseLike(callbackOutput)) {
|
21295
21369
|
return callbackOutput.then(function() {
|
21296
21370
|
return makePromise(value, isResolved);
|
21297
21371
|
}, function(error) {
|
@@ -21316,7 +21390,7 @@ function qFactory(nextTick, exceptionHandler) {
|
|
21316
21390
|
|
21317
21391
|
|
21318
21392
|
var ref = function(value) {
|
21319
|
-
if (
|
21393
|
+
if (isPromiseLike(value)) return value;
|
21320
21394
|
return {
|
21321
21395
|
then: function(callback) {
|
21322
21396
|
var result = defer();
|
@@ -21983,7 +22057,7 @@ function $RootScopeProvider(){
|
|
21983
22057
|
|
21984
22058
|
function $watchCollectionWatch() {
|
21985
22059
|
newValue = objGetter(self);
|
21986
|
-
var newLength, key;
|
22060
|
+
var newLength, key, bothNaN;
|
21987
22061
|
|
21988
22062
|
if (!isObject(newValue)) { // if primitive
|
21989
22063
|
if (oldValue !== newValue) {
|
@@ -22007,7 +22081,7 @@ function $RootScopeProvider(){
|
|
22007
22081
|
}
|
22008
22082
|
// copy the items to oldValue and look for changes.
|
22009
22083
|
for (var i = 0; i < newLength; i++) {
|
22010
|
-
|
22084
|
+
bothNaN = (oldValue[i] !== oldValue[i]) &&
|
22011
22085
|
(newValue[i] !== newValue[i]);
|
22012
22086
|
if (!bothNaN && (oldValue[i] !== newValue[i])) {
|
22013
22087
|
changeDetected++;
|
@@ -22027,7 +22101,9 @@ function $RootScopeProvider(){
|
|
22027
22101
|
if (newValue.hasOwnProperty(key)) {
|
22028
22102
|
newLength++;
|
22029
22103
|
if (oldValue.hasOwnProperty(key)) {
|
22030
|
-
|
22104
|
+
bothNaN = (oldValue[key] !== oldValue[key]) &&
|
22105
|
+
(newValue[key] !== newValue[key]);
|
22106
|
+
if (!bothNaN && (oldValue[key] !== newValue[key])) {
|
22031
22107
|
changeDetected++;
|
22032
22108
|
oldValue[key] = newValue[key];
|
22033
22109
|
}
|
@@ -22179,7 +22255,7 @@ function $RootScopeProvider(){
|
|
22179
22255
|
if ((value = watch.get(current)) !== (last = watch.last) &&
|
22180
22256
|
!(watch.eq
|
22181
22257
|
? equals(value, last)
|
22182
|
-
: (typeof value
|
22258
|
+
: (typeof value === 'number' && typeof last === 'number'
|
22183
22259
|
&& isNaN(value) && isNaN(last)))) {
|
22184
22260
|
dirty = true;
|
22185
22261
|
lastDirtyWatch = watch;
|
@@ -22872,19 +22948,21 @@ function adjustMatchers(matchers) {
|
|
22872
22948
|
*
|
22873
22949
|
* Here is what a secure configuration for this scenario might look like:
|
22874
22950
|
*
|
22875
|
-
*
|
22876
|
-
*
|
22877
|
-
*
|
22878
|
-
*
|
22879
|
-
*
|
22880
|
-
*
|
22881
|
-
*
|
22882
|
-
*
|
22883
|
-
*
|
22884
|
-
*
|
22885
|
-
*
|
22886
|
-
*
|
22887
|
-
*
|
22951
|
+
* ```
|
22952
|
+
* angular.module('myApp', []).config(function($sceDelegateProvider) {
|
22953
|
+
* $sceDelegateProvider.resourceUrlWhitelist([
|
22954
|
+
* // Allow same origin resource loads.
|
22955
|
+
* 'self',
|
22956
|
+
* // Allow loading from our assets domain. Notice the difference between * and **.
|
22957
|
+
* 'http://srv*.assets.example.com/**'
|
22958
|
+
* ]);
|
22959
|
+
*
|
22960
|
+
* // The blacklist overrides the whitelist so the open redirect here is blocked.
|
22961
|
+
* $sceDelegateProvider.resourceUrlBlacklist([
|
22962
|
+
* 'http://myapp.example.com/clickThru**'
|
22963
|
+
* ]);
|
22964
|
+
* });
|
22965
|
+
* ```
|
22888
22966
|
*/
|
22889
22967
|
|
22890
22968
|
function $SceDelegateProvider() {
|
@@ -23179,10 +23257,10 @@ function $SceDelegateProvider() {
|
|
23179
23257
|
*
|
23180
23258
|
* Here's an example of a binding in a privileged context:
|
23181
23259
|
*
|
23182
|
-
*
|
23183
|
-
*
|
23184
|
-
*
|
23185
|
-
*
|
23260
|
+
* ```
|
23261
|
+
* <input ng-model="userHtml">
|
23262
|
+
* <div ng-bind-html="userHtml"></div>
|
23263
|
+
* ```
|
23186
23264
|
*
|
23187
23265
|
* Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE
|
23188
23266
|
* disabled, this application allows the user to render arbitrary HTML into the DIV.
|
@@ -23222,15 +23300,15 @@ function $SceDelegateProvider() {
|
|
23222
23300
|
* ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly
|
23223
23301
|
* simplified):
|
23224
23302
|
*
|
23225
|
-
*
|
23226
|
-
*
|
23227
|
-
*
|
23228
|
-
*
|
23229
|
-
*
|
23230
|
-
*
|
23231
|
-
*
|
23232
|
-
*
|
23233
|
-
*
|
23303
|
+
* ```
|
23304
|
+
* var ngBindHtmlDirective = ['$sce', function($sce) {
|
23305
|
+
* return function(scope, element, attr) {
|
23306
|
+
* scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
|
23307
|
+
* element.html(value || '');
|
23308
|
+
* });
|
23309
|
+
* };
|
23310
|
+
* }];
|
23311
|
+
* ```
|
23234
23312
|
*
|
23235
23313
|
* ## Impact on loading templates
|
23236
23314
|
*
|
@@ -23334,66 +23412,65 @@ function $SceDelegateProvider() {
|
|
23334
23412
|
*
|
23335
23413
|
* ## Show me an example using SCE.
|
23336
23414
|
*
|
23337
|
-
*
|
23338
|
-
<
|
23339
|
-
<
|
23340
|
-
|
23341
|
-
|
23342
|
-
|
23343
|
-
|
23344
|
-
|
23345
|
-
|
23346
|
-
|
23347
|
-
|
23348
|
-
|
23349
|
-
|
23350
|
-
|
23351
|
-
|
23352
|
-
|
23353
|
-
|
23354
|
-
|
23355
|
-
|
23356
|
-
|
23357
|
-
|
23358
|
-
|
23359
|
-
|
23360
|
-
|
23361
|
-
|
23362
|
-
|
23363
|
-
|
23364
|
-
|
23365
|
-
|
23366
|
-
|
23367
|
-
|
23368
|
-
|
23369
|
-
|
23370
|
-
|
23371
|
-
|
23372
|
-
|
23373
|
-
|
23374
|
-
|
23375
|
-
|
23376
|
-
|
23377
|
-
|
23378
|
-
|
23379
|
-
|
23380
|
-
|
23381
|
-
|
23382
|
-
|
23383
|
-
|
23384
|
-
|
23385
|
-
|
23386
|
-
|
23387
|
-
|
23388
|
-
|
23389
|
-
|
23390
|
-
|
23391
|
-
|
23392
|
-
|
23393
|
-
|
23394
|
-
|
23395
|
-
</
|
23396
|
-
</example>
|
23415
|
+
* <example module="mySceApp" deps="angular-sanitize.js">
|
23416
|
+
* <file name="index.html">
|
23417
|
+
* <div ng-controller="myAppController as myCtrl">
|
23418
|
+
* <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
|
23419
|
+
* <b>User comments</b><br>
|
23420
|
+
* By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
|
23421
|
+
* $sanitize is available. If $sanitize isn't available, this results in an error instead of an
|
23422
|
+
* exploit.
|
23423
|
+
* <div class="well">
|
23424
|
+
* <div ng-repeat="userComment in myCtrl.userComments">
|
23425
|
+
* <b>{{userComment.name}}</b>:
|
23426
|
+
* <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
|
23427
|
+
* <br>
|
23428
|
+
* </div>
|
23429
|
+
* </div>
|
23430
|
+
* </div>
|
23431
|
+
* </file>
|
23432
|
+
*
|
23433
|
+
* <file name="script.js">
|
23434
|
+
* var mySceApp = angular.module('mySceApp', ['ngSanitize']);
|
23435
|
+
*
|
23436
|
+
* mySceApp.controller("myAppController", function myAppController($http, $templateCache, $sce) {
|
23437
|
+
* var self = this;
|
23438
|
+
* $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
|
23439
|
+
* self.userComments = userComments;
|
23440
|
+
* });
|
23441
|
+
* self.explicitlyTrustedHtml = $sce.trustAsHtml(
|
23442
|
+
* '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' +
|
23443
|
+
* 'sanitization."">Hover over this text.</span>');
|
23444
|
+
* });
|
23445
|
+
* </file>
|
23446
|
+
*
|
23447
|
+
* <file name="test_data.json">
|
23448
|
+
* [
|
23449
|
+
* { "name": "Alice",
|
23450
|
+
* "htmlComment":
|
23451
|
+
* "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
|
23452
|
+
* },
|
23453
|
+
* { "name": "Bob",
|
23454
|
+
* "htmlComment": "<i>Yes!</i> Am I the only other one?"
|
23455
|
+
* }
|
23456
|
+
* ]
|
23457
|
+
* </file>
|
23458
|
+
*
|
23459
|
+
* <file name="protractor.js" type="protractor">
|
23460
|
+
* describe('SCE doc demo', function() {
|
23461
|
+
* it('should sanitize untrusted values', function() {
|
23462
|
+
* expect(element.all(by.css('.htmlComment')).first().getInnerHtml())
|
23463
|
+
* .toBe('<span>Is <i>anyone</i> reading this?</span>');
|
23464
|
+
* });
|
23465
|
+
*
|
23466
|
+
* it('should NOT sanitize explicitly trusted values', function() {
|
23467
|
+
* expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(
|
23468
|
+
* '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' +
|
23469
|
+
* 'sanitization."">Hover over this text.</span>');
|
23470
|
+
* });
|
23471
|
+
* });
|
23472
|
+
* </file>
|
23473
|
+
* </example>
|
23397
23474
|
*
|
23398
23475
|
*
|
23399
23476
|
*
|
@@ -23407,13 +23484,13 @@ function $SceDelegateProvider() {
|
|
23407
23484
|
*
|
23408
23485
|
* That said, here's how you can completely disable SCE:
|
23409
23486
|
*
|
23410
|
-
*
|
23411
|
-
*
|
23412
|
-
*
|
23413
|
-
*
|
23414
|
-
*
|
23415
|
-
*
|
23416
|
-
*
|
23487
|
+
* ```
|
23488
|
+
* angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
|
23489
|
+
* // Completely disable SCE. For demonstration purposes only!
|
23490
|
+
* // Do not use in new projects.
|
23491
|
+
* $sceProvider.enabled(false);
|
23492
|
+
* });
|
23493
|
+
* ```
|
23417
23494
|
*
|
23418
23495
|
*/
|
23419
23496
|
/* jshint maxlen: 100 */
|
@@ -23524,7 +23601,7 @@ function $SceProvider() {
|
|
23524
23601
|
|
23525
23602
|
/**
|
23526
23603
|
* @ngdoc method
|
23527
|
-
* @name $sce#
|
23604
|
+
* @name $sce#parseAs
|
23528
23605
|
*
|
23529
23606
|
* @description
|
23530
23607
|
* Converts Angular {@link guide/expression expression} into a function. This is like {@link
|
@@ -24110,17 +24187,18 @@ function urlIsSameOrigin(requestUrl) {
|
|
24110
24187
|
* expression.
|
24111
24188
|
*
|
24112
24189
|
* @example
|
24113
|
-
<example>
|
24190
|
+
<example module="windowExample">
|
24114
24191
|
<file name="index.html">
|
24115
24192
|
<script>
|
24116
|
-
|
24117
|
-
$scope
|
24118
|
-
|
24193
|
+
angular.module('windowExample', [])
|
24194
|
+
.controller('ExampleController', ['$scope', '$window', function ($scope, $window) {
|
24195
|
+
$scope.greeting = 'Hello, World!';
|
24196
|
+
$scope.doGreeting = function(greeting) {
|
24119
24197
|
$window.alert(greeting);
|
24120
|
-
|
24121
|
-
|
24198
|
+
};
|
24199
|
+
}]);
|
24122
24200
|
</script>
|
24123
|
-
<div ng-controller="
|
24201
|
+
<div ng-controller="ExampleController">
|
24124
24202
|
<input type="text" ng-model="greeting" />
|
24125
24203
|
<button ng-click="doGreeting(greeting)">ALERT</button>
|
24126
24204
|
</div>
|
@@ -24138,6 +24216,17 @@ function $WindowProvider(){
|
|
24138
24216
|
this.$get = valueFn(window);
|
24139
24217
|
}
|
24140
24218
|
|
24219
|
+
/* global currencyFilter: true,
|
24220
|
+
dateFilter: true,
|
24221
|
+
filterFilter: true,
|
24222
|
+
jsonFilter: true,
|
24223
|
+
limitToFilter: true,
|
24224
|
+
lowercaseFilter: true,
|
24225
|
+
numberFilter: true,
|
24226
|
+
orderByFilter: true,
|
24227
|
+
uppercaseFilter: true,
|
24228
|
+
*/
|
24229
|
+
|
24141
24230
|
/**
|
24142
24231
|
* @ngdoc provider
|
24143
24232
|
* @name $filterProvider
|
@@ -24480,7 +24569,7 @@ function filterFilter() {
|
|
24480
24569
|
// jshint +W086
|
24481
24570
|
for (var key in expression) {
|
24482
24571
|
(function(path) {
|
24483
|
-
if (typeof expression[path]
|
24572
|
+
if (typeof expression[path] === 'undefined') return;
|
24484
24573
|
predicates.push(function(value) {
|
24485
24574
|
return search(path == '$' ? value : (value && value[path]), expression[path]);
|
24486
24575
|
});
|
@@ -24519,14 +24608,15 @@ function filterFilter() {
|
|
24519
24608
|
*
|
24520
24609
|
*
|
24521
24610
|
* @example
|
24522
|
-
<example>
|
24611
|
+
<example module="currencyExample">
|
24523
24612
|
<file name="index.html">
|
24524
24613
|
<script>
|
24525
|
-
|
24526
|
-
$scope
|
24527
|
-
|
24614
|
+
angular.module('currencyExample', [])
|
24615
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
24616
|
+
$scope.amount = 1234.56;
|
24617
|
+
}]);
|
24528
24618
|
</script>
|
24529
|
-
<div ng-controller="
|
24619
|
+
<div ng-controller="ExampleController">
|
24530
24620
|
<input type="number" ng-model="amount"> <br>
|
24531
24621
|
default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br>
|
24532
24622
|
custom currency identifier (USD$): <span>{{amount | currency:"USD$"}}</span>
|
@@ -24578,14 +24668,15 @@ function currencyFilter($locale) {
|
|
24578
24668
|
* @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
|
24579
24669
|
*
|
24580
24670
|
* @example
|
24581
|
-
<example>
|
24671
|
+
<example module="numberFilterExample">
|
24582
24672
|
<file name="index.html">
|
24583
24673
|
<script>
|
24584
|
-
|
24585
|
-
$scope
|
24586
|
-
|
24674
|
+
angular.module('numberFilterExample', [])
|
24675
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
24676
|
+
$scope.val = 1234.56789;
|
24677
|
+
}]);
|
24587
24678
|
</script>
|
24588
|
-
<div ng-controller="
|
24679
|
+
<div ng-controller="ExampleController">
|
24589
24680
|
Enter number: <input ng-model='val'><br>
|
24590
24681
|
Default formatting: <span id='number-default'>{{val | number}}</span><br>
|
24591
24682
|
No fractions: <span>{{val | number:0}}</span><br>
|
@@ -24635,6 +24726,7 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
|
|
24635
24726
|
var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
|
24636
24727
|
if (match && match[2] == '-' && match[3] > fractionSize + 1) {
|
24637
24728
|
numStr = '0';
|
24729
|
+
number = 0;
|
24638
24730
|
} else {
|
24639
24731
|
formatedText = numStr;
|
24640
24732
|
hasExponent = true;
|
@@ -24649,8 +24741,11 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
|
|
24649
24741
|
fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
|
24650
24742
|
}
|
24651
24743
|
|
24652
|
-
|
24653
|
-
|
24744
|
+
// safely round numbers in JS without hitting imprecisions of floating-point arithmetics
|
24745
|
+
// inspired by:
|
24746
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
|
24747
|
+
number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
|
24748
|
+
|
24654
24749
|
var fraction = ('' + number).split(DECIMAL_SEP);
|
24655
24750
|
var whole = fraction[0];
|
24656
24751
|
fraction = fraction[1] || '';
|
@@ -24893,11 +24988,7 @@ function dateFilter($locale) {
|
|
24893
24988
|
format = format || 'mediumDate';
|
24894
24989
|
format = $locale.DATETIME_FORMATS[format] || format;
|
24895
24990
|
if (isString(date)) {
|
24896
|
-
|
24897
|
-
date = int(date);
|
24898
|
-
} else {
|
24899
|
-
date = jsonStringToDate(date);
|
24900
|
-
}
|
24991
|
+
date = NUMBER_STRING.test(date) ? int(date) : jsonStringToDate(date);
|
24901
24992
|
}
|
24902
24993
|
|
24903
24994
|
if (isNumber(date)) {
|
@@ -25005,17 +25096,18 @@ var uppercaseFilter = valueFn(uppercase);
|
|
25005
25096
|
* had less than `limit` elements.
|
25006
25097
|
*
|
25007
25098
|
* @example
|
25008
|
-
<example>
|
25099
|
+
<example module="limitToExample">
|
25009
25100
|
<file name="index.html">
|
25010
25101
|
<script>
|
25011
|
-
|
25012
|
-
$scope
|
25013
|
-
|
25014
|
-
|
25015
|
-
|
25016
|
-
|
25102
|
+
angular.module('limitToExample', [])
|
25103
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
25104
|
+
$scope.numbers = [1,2,3,4,5,6,7,8,9];
|
25105
|
+
$scope.letters = "abcdefghi";
|
25106
|
+
$scope.numLimit = 3;
|
25107
|
+
$scope.letterLimit = 3;
|
25108
|
+
}]);
|
25017
25109
|
</script>
|
25018
|
-
<div ng-controller="
|
25110
|
+
<div ng-controller="ExampleController">
|
25019
25111
|
Limit {{numbers}} to: <input type="integer" ng-model="numLimit">
|
25020
25112
|
<p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
|
25021
25113
|
Limit {{letters}} to: <input type="integer" ng-model="letterLimit">
|
@@ -25127,20 +25219,21 @@ function limitToFilter(){
|
|
25127
25219
|
* @returns {Array} Sorted copy of the source array.
|
25128
25220
|
*
|
25129
25221
|
* @example
|
25130
|
-
<example>
|
25222
|
+
<example module="orderByExample">
|
25131
25223
|
<file name="index.html">
|
25132
25224
|
<script>
|
25133
|
-
|
25134
|
-
$scope
|
25135
|
-
|
25136
|
-
|
25137
|
-
|
25138
|
-
|
25139
|
-
|
25140
|
-
|
25141
|
-
|
25225
|
+
angular.module('orderByExample', [])
|
25226
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
25227
|
+
$scope.friends =
|
25228
|
+
[{name:'John', phone:'555-1212', age:10},
|
25229
|
+
{name:'Mary', phone:'555-9876', age:19},
|
25230
|
+
{name:'Mike', phone:'555-4321', age:21},
|
25231
|
+
{name:'Adam', phone:'555-5678', age:35},
|
25232
|
+
{name:'Julie', phone:'555-8765', age:29}];
|
25233
|
+
$scope.predicate = '-age';
|
25234
|
+
}]);
|
25142
25235
|
</script>
|
25143
|
-
<div ng-controller="
|
25236
|
+
<div ng-controller="ExampleController">
|
25144
25237
|
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
|
25145
25238
|
<hr/>
|
25146
25239
|
[ <a href="" ng-click="predicate=''">unsorted</a> ]
|
@@ -25168,9 +25261,9 @@ function limitToFilter(){
|
|
25168
25261
|
* Example:
|
25169
25262
|
*
|
25170
25263
|
* @example
|
25171
|
-
<example>
|
25264
|
+
<example module="orderByExample">
|
25172
25265
|
<file name="index.html">
|
25173
|
-
<div ng-controller="
|
25266
|
+
<div ng-controller="ExampleController">
|
25174
25267
|
<table class="friend">
|
25175
25268
|
<tr>
|
25176
25269
|
<th><a href="" ng-click="reverse=false;order('name', false)">Name</a>
|
@@ -25188,21 +25281,21 @@ function limitToFilter(){
|
|
25188
25281
|
</file>
|
25189
25282
|
|
25190
25283
|
<file name="script.js">
|
25191
|
-
|
25192
|
-
|
25193
|
-
|
25194
|
-
|
25195
|
-
|
25196
|
-
|
25197
|
-
|
25198
|
-
|
25199
|
-
|
25200
|
-
|
25201
|
-
|
25202
|
-
|
25203
|
-
|
25204
|
-
|
25205
|
-
|
25284
|
+
angular.module('orderByExample', [])
|
25285
|
+
.controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {
|
25286
|
+
var orderBy = $filter('orderBy');
|
25287
|
+
$scope.friends = [
|
25288
|
+
{ name: 'John', phone: '555-1212', age: 10 },
|
25289
|
+
{ name: 'Mary', phone: '555-9876', age: 19 },
|
25290
|
+
{ name: 'Mike', phone: '555-4321', age: 21 },
|
25291
|
+
{ name: 'Adam', phone: '555-5678', age: 35 },
|
25292
|
+
{ name: 'Julie', phone: '555-8765', age: 29 }
|
25293
|
+
];
|
25294
|
+
$scope.order = function(predicate, reverse) {
|
25295
|
+
$scope.friends = orderBy($scope.friends, predicate, reverse);
|
25296
|
+
};
|
25297
|
+
$scope.order('-age',false);
|
25298
|
+
}]);
|
25206
25299
|
</file>
|
25207
25300
|
</example>
|
25208
25301
|
*/
|
@@ -25251,6 +25344,10 @@ function orderByFilter($parse){
|
|
25251
25344
|
var t1 = typeof v1;
|
25252
25345
|
var t2 = typeof v2;
|
25253
25346
|
if (t1 == t2) {
|
25347
|
+
if (isDate(v1) && isDate(v2)) {
|
25348
|
+
v1 = v1.valueOf();
|
25349
|
+
v2 = v2.valueOf();
|
25350
|
+
}
|
25254
25351
|
if (t1 == "string") {
|
25255
25352
|
v1 = v1.toLowerCase();
|
25256
25353
|
v2 = v2.toLowerCase();
|
@@ -25388,7 +25485,7 @@ var htmlAnchorDirective = valueFn({
|
|
25388
25485
|
return browser.driver.getCurrentUrl().then(function(url) {
|
25389
25486
|
return url.match(/\/123$/);
|
25390
25487
|
});
|
25391
|
-
},
|
25488
|
+
}, 5000, 'page should navigate to /123');
|
25392
25489
|
});
|
25393
25490
|
|
25394
25491
|
xit('should execute ng-click but not reload when href empty string and name specified', function() {
|
@@ -25416,7 +25513,7 @@ var htmlAnchorDirective = valueFn({
|
|
25416
25513
|
return browser.driver.getCurrentUrl().then(function(url) {
|
25417
25514
|
return url.match(/\/6$/);
|
25418
25515
|
});
|
25419
|
-
},
|
25516
|
+
}, 5000, 'page should navigate to /6');
|
25420
25517
|
});
|
25421
25518
|
</file>
|
25422
25519
|
</example>
|
@@ -26032,12 +26129,13 @@ function FormController(element, attrs, $scope, $animate) {
|
|
26032
26129
|
* </pre>
|
26033
26130
|
*
|
26034
26131
|
* @example
|
26035
|
-
<example deps="angular-animate.js" animations="true" fixBase="true">
|
26132
|
+
<example deps="angular-animate.js" animations="true" fixBase="true" module="formExample">
|
26036
26133
|
<file name="index.html">
|
26037
26134
|
<script>
|
26038
|
-
|
26039
|
-
$scope
|
26040
|
-
|
26135
|
+
angular.module('formExample', [])
|
26136
|
+
.controller('FormController', ['$scope', function($scope) {
|
26137
|
+
$scope.userType = 'guest';
|
26138
|
+
}]);
|
26041
26139
|
</script>
|
26042
26140
|
<style>
|
26043
26141
|
.my-form {
|
@@ -26049,7 +26147,7 @@ function FormController(element, attrs, $scope, $animate) {
|
|
26049
26147
|
background: red;
|
26050
26148
|
}
|
26051
26149
|
</style>
|
26052
|
-
<form name="myForm" ng-controller="
|
26150
|
+
<form name="myForm" ng-controller="FormController" class="my-form">
|
26053
26151
|
userType: <input name="input" ng-model="userType" required>
|
26054
26152
|
<span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
|
26055
26153
|
<tt>userType = {{userType}}</tt><br>
|
@@ -26143,16 +26241,14 @@ var formDirectiveFactory = function(isNgForm) {
|
|
26143
26241
|
var formDirective = formDirectiveFactory();
|
26144
26242
|
var ngFormDirective = formDirectiveFactory(true);
|
26145
26243
|
|
26146
|
-
/* global
|
26147
|
-
|
26148
|
-
|
26149
|
-
|
26150
|
-
-PRISTINE_CLASS,
|
26151
|
-
-DIRTY_CLASS
|
26244
|
+
/* global VALID_CLASS: true,
|
26245
|
+
INVALID_CLASS: true,
|
26246
|
+
PRISTINE_CLASS: true,
|
26247
|
+
DIRTY_CLASS: true
|
26152
26248
|
*/
|
26153
26249
|
|
26154
26250
|
var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
|
26155
|
-
var EMAIL_REGEXP = /^[a-z0-9!#$%&'
|
26251
|
+
var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
|
26156
26252
|
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
|
26157
26253
|
|
26158
26254
|
var inputType = {
|
@@ -26182,15 +26278,16 @@ var inputType = {
|
|
26182
26278
|
* @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
|
26183
26279
|
*
|
26184
26280
|
* @example
|
26185
|
-
<example name="text-input-directive">
|
26281
|
+
<example name="text-input-directive" module="textInputExample">
|
26186
26282
|
<file name="index.html">
|
26187
26283
|
<script>
|
26188
|
-
|
26189
|
-
$scope
|
26190
|
-
|
26191
|
-
|
26284
|
+
angular.module('textInputExample', [])
|
26285
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
26286
|
+
$scope.text = 'guest';
|
26287
|
+
$scope.word = /^\s*\w*\s*$/;
|
26288
|
+
}]);
|
26192
26289
|
</script>
|
26193
|
-
<form name="myForm" ng-controller="
|
26290
|
+
<form name="myForm" ng-controller="ExampleController">
|
26194
26291
|
Single word: <input type="text" name="input" ng-model="text"
|
26195
26292
|
ng-pattern="word" required ng-trim="false">
|
26196
26293
|
<span class="error" ng-show="myForm.input.$error.required">
|
@@ -26262,14 +26359,15 @@ var inputType = {
|
|
26262
26359
|
* interaction with the input element.
|
26263
26360
|
*
|
26264
26361
|
* @example
|
26265
|
-
<example name="number-input-directive">
|
26362
|
+
<example name="number-input-directive" module="numberExample">
|
26266
26363
|
<file name="index.html">
|
26267
26364
|
<script>
|
26268
|
-
|
26269
|
-
$scope
|
26270
|
-
|
26365
|
+
angular.module('numberExample', [])
|
26366
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
26367
|
+
$scope.value = 12;
|
26368
|
+
}]);
|
26271
26369
|
</script>
|
26272
|
-
<form name="myForm" ng-controller="
|
26370
|
+
<form name="myForm" ng-controller="ExampleController">
|
26273
26371
|
Number: <input type="number" name="input" ng-model="value"
|
26274
26372
|
min="0" max="99" required>
|
26275
26373
|
<span class="error" ng-show="myForm.input.$error.required">
|
@@ -26337,14 +26435,15 @@ var inputType = {
|
|
26337
26435
|
* interaction with the input element.
|
26338
26436
|
*
|
26339
26437
|
* @example
|
26340
|
-
<example name="url-input-directive">
|
26438
|
+
<example name="url-input-directive" module="urlExample">
|
26341
26439
|
<file name="index.html">
|
26342
26440
|
<script>
|
26343
|
-
|
26344
|
-
$scope
|
26345
|
-
|
26441
|
+
angular.module('urlExample', [])
|
26442
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
26443
|
+
$scope.text = 'http://google.com';
|
26444
|
+
}]);
|
26346
26445
|
</script>
|
26347
|
-
<form name="myForm" ng-controller="
|
26446
|
+
<form name="myForm" ng-controller="ExampleController">
|
26348
26447
|
URL: <input type="url" name="input" ng-model="text" required>
|
26349
26448
|
<span class="error" ng-show="myForm.input.$error.required">
|
26350
26449
|
Required!</span>
|
@@ -26413,14 +26512,15 @@ var inputType = {
|
|
26413
26512
|
* interaction with the input element.
|
26414
26513
|
*
|
26415
26514
|
* @example
|
26416
|
-
<example name="email-input-directive">
|
26515
|
+
<example name="email-input-directive" module="emailExample">
|
26417
26516
|
<file name="index.html">
|
26418
26517
|
<script>
|
26419
|
-
|
26420
|
-
$scope
|
26421
|
-
|
26518
|
+
angular.module('emailExample', [])
|
26519
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
26520
|
+
$scope.text = 'me@example.com';
|
26521
|
+
}]);
|
26422
26522
|
</script>
|
26423
|
-
<form name="myForm" ng-controller="
|
26523
|
+
<form name="myForm" ng-controller="ExampleController">
|
26424
26524
|
Email: <input type="email" name="input" ng-model="text" required>
|
26425
26525
|
<span class="error" ng-show="myForm.input.$error.required">
|
26426
26526
|
Required!</span>
|
@@ -26479,18 +26579,19 @@ var inputType = {
|
|
26479
26579
|
* be set when selected.
|
26480
26580
|
*
|
26481
26581
|
* @example
|
26482
|
-
<example name="radio-input-directive">
|
26582
|
+
<example name="radio-input-directive" module="radioExample">
|
26483
26583
|
<file name="index.html">
|
26484
26584
|
<script>
|
26485
|
-
|
26486
|
-
$scope
|
26487
|
-
|
26488
|
-
|
26489
|
-
|
26490
|
-
|
26491
|
-
|
26585
|
+
angular.module('radioExample', [])
|
26586
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
26587
|
+
$scope.color = 'blue';
|
26588
|
+
$scope.specialValue = {
|
26589
|
+
"id": "12345",
|
26590
|
+
"value": "green"
|
26591
|
+
};
|
26592
|
+
}]);
|
26492
26593
|
</script>
|
26493
|
-
<form name="myForm" ng-controller="
|
26594
|
+
<form name="myForm" ng-controller="ExampleController">
|
26494
26595
|
<input type="radio" ng-model="color" value="red"> Red <br/>
|
26495
26596
|
<input type="radio" ng-model="color" ng-value="specialValue"> Green <br/>
|
26496
26597
|
<input type="radio" ng-model="color" value="blue"> Blue <br/>
|
@@ -26529,15 +26630,16 @@ var inputType = {
|
|
26529
26630
|
* interaction with the input element.
|
26530
26631
|
*
|
26531
26632
|
* @example
|
26532
|
-
<example name="checkbox-input-directive">
|
26633
|
+
<example name="checkbox-input-directive" module="checkboxExample">
|
26533
26634
|
<file name="index.html">
|
26534
26635
|
<script>
|
26535
|
-
|
26536
|
-
$scope
|
26537
|
-
|
26538
|
-
|
26636
|
+
angular.module('checkboxExample', [])
|
26637
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
26638
|
+
$scope.value1 = true;
|
26639
|
+
$scope.value2 = 'YES'
|
26640
|
+
}]);
|
26539
26641
|
</script>
|
26540
|
-
<form name="myForm" ng-controller="
|
26642
|
+
<form name="myForm" ng-controller="ExampleController">
|
26541
26643
|
Value1: <input type="checkbox" ng-model="value1"> <br/>
|
26542
26644
|
Value2: <input type="checkbox" ng-model="value2"
|
26543
26645
|
ng-true-value="YES" ng-false-value="NO"> <br/>
|
@@ -26578,15 +26680,29 @@ function validate(ctrl, validatorName, validity, value){
|
|
26578
26680
|
return validity ? value : undefined;
|
26579
26681
|
}
|
26580
26682
|
|
26683
|
+
function testFlags(validity, flags) {
|
26684
|
+
var i, flag;
|
26685
|
+
if (flags) {
|
26686
|
+
for (i=0; i<flags.length; ++i) {
|
26687
|
+
flag = flags[i];
|
26688
|
+
if (validity[flag]) {
|
26689
|
+
return true;
|
26690
|
+
}
|
26691
|
+
}
|
26692
|
+
}
|
26693
|
+
return false;
|
26694
|
+
}
|
26581
26695
|
|
26582
|
-
|
26583
|
-
|
26696
|
+
// Pass validity so that behaviour can be mocked easier.
|
26697
|
+
function addNativeHtml5Validators(ctrl, validatorName, badFlags, ignoreFlags, validity) {
|
26584
26698
|
if (isObject(validity)) {
|
26699
|
+
ctrl.$$hasNativeValidators = true;
|
26585
26700
|
var validator = function(value) {
|
26586
26701
|
// Don't overwrite previous validation, don't consider valueMissing to apply (ng-required can
|
26587
26702
|
// perform the required validation)
|
26588
|
-
if (!ctrl.$error[validatorName] &&
|
26589
|
-
validity
|
26703
|
+
if (!ctrl.$error[validatorName] &&
|
26704
|
+
!testFlags(validity, ignoreFlags) &&
|
26705
|
+
testFlags(validity, badFlags)) {
|
26590
26706
|
ctrl.$setValidity(validatorName, false);
|
26591
26707
|
return;
|
26592
26708
|
}
|
@@ -26597,8 +26713,9 @@ function addNativeHtml5Validators(ctrl, validatorName, element) {
|
|
26597
26713
|
}
|
26598
26714
|
|
26599
26715
|
function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
|
26600
|
-
var validity = element.prop(
|
26716
|
+
var validity = element.prop(VALIDITY_STATE_PROPERTY);
|
26601
26717
|
var placeholder = element[0].placeholder, noevent = {};
|
26718
|
+
ctrl.$$validityState = validity;
|
26602
26719
|
|
26603
26720
|
// In composition mode, users are still inputing intermediate text buffer,
|
26604
26721
|
// hold the listener until composition is done.
|
@@ -26636,11 +26753,11 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
|
|
26636
26753
|
value = trim(value);
|
26637
26754
|
}
|
26638
26755
|
|
26639
|
-
|
26640
|
-
|
26641
|
-
|
26642
|
-
|
26643
|
-
|
26756
|
+
// If a control is suffering from bad input, browsers discard its value, so it may be
|
26757
|
+
// necessary to revalidate even if the control's value is the same empty value twice in
|
26758
|
+
// a row.
|
26759
|
+
var revalidate = validity && ctrl.$$hasNativeValidators;
|
26760
|
+
if (ctrl.$viewValue !== value || (value === '' && revalidate)) {
|
26644
26761
|
if (scope.$$phase) {
|
26645
26762
|
ctrl.$setViewValue(value);
|
26646
26763
|
} else {
|
@@ -26746,6 +26863,8 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
|
|
26746
26863
|
}
|
26747
26864
|
}
|
26748
26865
|
|
26866
|
+
var numberBadFlags = ['badInput'];
|
26867
|
+
|
26749
26868
|
function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
|
26750
26869
|
textInputType(scope, element, attr, ctrl, $sniffer, $browser);
|
26751
26870
|
|
@@ -26760,7 +26879,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
|
|
26760
26879
|
}
|
26761
26880
|
});
|
26762
26881
|
|
26763
|
-
addNativeHtml5Validators(ctrl, 'number',
|
26882
|
+
addNativeHtml5Validators(ctrl, 'number', numberBadFlags, null, ctrl.$$validityState);
|
26764
26883
|
|
26765
26884
|
ctrl.$formatters.push(function(value) {
|
26766
26885
|
return ctrl.$isEmpty(value) ? '' : '' + value;
|
@@ -26920,14 +27039,15 @@ function checkboxInputType(scope, element, attr, ctrl) {
|
|
26920
27039
|
* interaction with the input element.
|
26921
27040
|
*
|
26922
27041
|
* @example
|
26923
|
-
<example name="input-directive">
|
27042
|
+
<example name="input-directive" module="inputExample">
|
26924
27043
|
<file name="index.html">
|
26925
27044
|
<script>
|
26926
|
-
|
26927
|
-
|
26928
|
-
|
27045
|
+
angular.module('inputExample', [])
|
27046
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
27047
|
+
$scope.user = {name: 'guest', last: 'visitor'};
|
27048
|
+
}]);
|
26929
27049
|
</script>
|
26930
|
-
<div ng-controller="
|
27050
|
+
<div ng-controller="ExampleController">
|
26931
27051
|
<form name="myForm">
|
26932
27052
|
User name: <input type="text" name="userName" ng-model="user.name" required>
|
26933
27053
|
<span class="error" ng-show="myForm.userName.$error.required">
|
@@ -27242,7 +27362,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
27242
27362
|
* This method should be called by validators - i.e. the parser or formatter functions.
|
27243
27363
|
*
|
27244
27364
|
* @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign
|
27245
|
-
* to `$error[validationErrorKey]
|
27365
|
+
* to `$error[validationErrorKey]=!isValid` so that it is available for data-binding.
|
27246
27366
|
* The `validationErrorKey` should be in camelCase and will get converted into dash-case
|
27247
27367
|
* for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
|
27248
27368
|
* class and can be bound to as `{{someForm.someControl.$error.myError}}` .
|
@@ -27445,12 +27565,13 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
27445
27565
|
* </pre>
|
27446
27566
|
*
|
27447
27567
|
* @example
|
27448
|
-
* <example deps="angular-animate.js" animations="true" fixBase="true">
|
27568
|
+
* <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample">
|
27449
27569
|
<file name="index.html">
|
27450
27570
|
<script>
|
27451
|
-
|
27452
|
-
$scope
|
27453
|
-
|
27571
|
+
angular.module('inputExample', [])
|
27572
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
27573
|
+
$scope.val = '1';
|
27574
|
+
}]);
|
27454
27575
|
</script>
|
27455
27576
|
<style>
|
27456
27577
|
.my-input {
|
@@ -27465,7 +27586,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
27465
27586
|
</style>
|
27466
27587
|
Update input to see transitions when valid/invalid.
|
27467
27588
|
Integer is a valid value.
|
27468
|
-
<form name="testForm" ng-controller="
|
27589
|
+
<form name="testForm" ng-controller="ExampleController">
|
27469
27590
|
<input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input" />
|
27470
27591
|
</form>
|
27471
27592
|
</file>
|
@@ -27509,17 +27630,18 @@ var ngModelDirective = function() {
|
|
27509
27630
|
* in input value.
|
27510
27631
|
*
|
27511
27632
|
* @example
|
27512
|
-
* <example name="ngChange-directive">
|
27633
|
+
* <example name="ngChange-directive" module="changeExample">
|
27513
27634
|
* <file name="index.html">
|
27514
27635
|
* <script>
|
27515
|
-
*
|
27516
|
-
* $scope
|
27517
|
-
*
|
27518
|
-
* $scope.
|
27519
|
-
*
|
27520
|
-
*
|
27636
|
+
* angular.module('changeExample', [])
|
27637
|
+
* .controller('ExampleController', ['$scope', function($scope) {
|
27638
|
+
* $scope.counter = 0;
|
27639
|
+
* $scope.change = function() {
|
27640
|
+
* $scope.counter++;
|
27641
|
+
* };
|
27642
|
+
* }]);
|
27521
27643
|
* </script>
|
27522
|
-
* <div ng-controller="
|
27644
|
+
* <div ng-controller="ExampleController">
|
27523
27645
|
* <input type="checkbox" ng-model="confirmed" ng-change="change()" id="ng-change-example1" />
|
27524
27646
|
* <input type="checkbox" ng-model="confirmed" id="ng-change-example2" />
|
27525
27647
|
* <label for="ng-change-example2">Confirmed</label><br />
|
@@ -27600,14 +27722,15 @@ var requiredDirective = function() {
|
|
27600
27722
|
* specified in form `/something/` then the value will be converted into a regular expression.
|
27601
27723
|
*
|
27602
27724
|
* @example
|
27603
|
-
<example name="ngList-directive">
|
27725
|
+
<example name="ngList-directive" module="listExample">
|
27604
27726
|
<file name="index.html">
|
27605
27727
|
<script>
|
27606
|
-
|
27607
|
-
|
27608
|
-
|
27728
|
+
angular.module('listExample', [])
|
27729
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
27730
|
+
$scope.names = ['igor', 'misko', 'vojta'];
|
27731
|
+
}]);
|
27609
27732
|
</script>
|
27610
|
-
<form name="myForm" ng-controller="
|
27733
|
+
<form name="myForm" ng-controller="ExampleController">
|
27611
27734
|
List: <input name="namesInput" ng-model="names" ng-list required>
|
27612
27735
|
<span class="error" ng-show="myForm.namesInput.$error.required">
|
27613
27736
|
Required!</span>
|
@@ -27699,15 +27822,16 @@ var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
|
|
27699
27822
|
* of the `input` element
|
27700
27823
|
*
|
27701
27824
|
* @example
|
27702
|
-
<example name="ngValue-directive">
|
27825
|
+
<example name="ngValue-directive" module="valueExample">
|
27703
27826
|
<file name="index.html">
|
27704
27827
|
<script>
|
27705
|
-
|
27706
|
-
|
27707
|
-
|
27708
|
-
|
27828
|
+
angular.module('valueExample', [])
|
27829
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
27830
|
+
$scope.names = ['pizza', 'unicorns', 'robots'];
|
27831
|
+
$scope.my = { favorite: 'unicorns' };
|
27832
|
+
}]);
|
27709
27833
|
</script>
|
27710
|
-
<form ng-controller="
|
27834
|
+
<form ng-controller="ExampleController">
|
27711
27835
|
<h2>Which is your favorite?</h2>
|
27712
27836
|
<label ng-repeat="name in names" for="{{name}}">
|
27713
27837
|
{{name}}
|
@@ -27765,7 +27889,7 @@ var ngValueDirective = function() {
|
|
27765
27889
|
* Typically, you don't use `ngBind` directly, but instead you use the double curly markup like
|
27766
27890
|
* `{{ expression }}` which is similar but less verbose.
|
27767
27891
|
*
|
27768
|
-
* It is preferable to use `ngBind` instead of `{{ expression }}`
|
27892
|
+
* It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily
|
27769
27893
|
* displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an
|
27770
27894
|
* element attribute, it makes the bindings invisible to the user while the page is loading.
|
27771
27895
|
*
|
@@ -27778,14 +27902,15 @@ var ngValueDirective = function() {
|
|
27778
27902
|
*
|
27779
27903
|
* @example
|
27780
27904
|
* Enter a name in the Live Preview text box; the greeting below the text box changes instantly.
|
27781
|
-
<example>
|
27905
|
+
<example module="bindExample">
|
27782
27906
|
<file name="index.html">
|
27783
27907
|
<script>
|
27784
|
-
|
27785
|
-
$scope
|
27786
|
-
|
27908
|
+
angular.module('bindExample', [])
|
27909
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
27910
|
+
$scope.name = 'Whirled';
|
27911
|
+
}]);
|
27787
27912
|
</script>
|
27788
|
-
<div ng-controller="
|
27913
|
+
<div ng-controller="ExampleController">
|
27789
27914
|
Enter name: <input type="text" ng-model="name"><br>
|
27790
27915
|
Hello <span ng-bind="name"></span>!
|
27791
27916
|
</div>
|
@@ -27836,15 +27961,16 @@ var ngBindDirective = ngDirective({
|
|
27836
27961
|
*
|
27837
27962
|
* @example
|
27838
27963
|
* Try it here: enter text in text box and watch the greeting change.
|
27839
|
-
<example>
|
27964
|
+
<example module="bindExample">
|
27840
27965
|
<file name="index.html">
|
27841
27966
|
<script>
|
27842
|
-
|
27843
|
-
$scope
|
27844
|
-
|
27845
|
-
|
27967
|
+
angular.module('bindExample', [])
|
27968
|
+
.controller('ExampleController', ['$scope', function ($scope) {
|
27969
|
+
$scope.salutation = 'Hello';
|
27970
|
+
$scope.name = 'World';
|
27971
|
+
}]);
|
27846
27972
|
</script>
|
27847
|
-
<div ng-controller="
|
27973
|
+
<div ng-controller="ExampleController">
|
27848
27974
|
Salutation: <input type="text" ng-model="salutation"><br>
|
27849
27975
|
Name: <input type="text" ng-model="name"><br>
|
27850
27976
|
<pre ng-bind-template="{{salutation}} {{name}}!"></pre>
|
@@ -27902,20 +28028,20 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
|
|
27902
28028
|
* @example
|
27903
28029
|
Try it here: enter text in text box and watch the greeting change.
|
27904
28030
|
|
27905
|
-
<example module="
|
28031
|
+
<example module="bindHtmlExample" deps="angular-sanitize.js">
|
27906
28032
|
<file name="index.html">
|
27907
|
-
<div ng-controller="
|
28033
|
+
<div ng-controller="ExampleController">
|
27908
28034
|
<p ng-bind-html="myHTML"></p>
|
27909
28035
|
</div>
|
27910
28036
|
</file>
|
27911
28037
|
|
27912
28038
|
<file name="script.js">
|
27913
|
-
angular.module('
|
27914
|
-
|
27915
|
-
|
27916
|
-
|
27917
|
-
|
27918
|
-
|
28039
|
+
angular.module('bindHtmlExample', ['ngSanitize'])
|
28040
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
28041
|
+
$scope.myHTML =
|
28042
|
+
'I am an <code>HTML</code>string with ' +
|
28043
|
+
'<a href="#">links!</a> and other <em>stuff</em>';
|
28044
|
+
}]);
|
27919
28045
|
</file>
|
27920
28046
|
|
27921
28047
|
<file name="protractor.js" type="protractor">
|
@@ -27927,15 +28053,24 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
|
|
27927
28053
|
</example>
|
27928
28054
|
*/
|
27929
28055
|
var ngBindHtmlDirective = ['$sce', '$parse', function($sce, $parse) {
|
27930
|
-
return
|
27931
|
-
|
28056
|
+
return {
|
28057
|
+
compile: function (tElement) {
|
28058
|
+
tElement.addClass('ng-binding');
|
27932
28059
|
|
27933
|
-
|
27934
|
-
|
28060
|
+
return function (scope, element, attr) {
|
28061
|
+
element.data('$binding', attr.ngBindHtml);
|
27935
28062
|
|
27936
|
-
|
27937
|
-
|
27938
|
-
|
28063
|
+
var parsed = $parse(attr.ngBindHtml);
|
28064
|
+
|
28065
|
+
function getStringValue() {
|
28066
|
+
return (parsed(scope) || '').toString();
|
28067
|
+
}
|
28068
|
+
|
28069
|
+
scope.$watch(getStringValue, function ngBindHtmlWatchAction(value) {
|
28070
|
+
element.html($sce.getTrustedHtml(parsed(scope)) || '');
|
28071
|
+
});
|
28072
|
+
};
|
28073
|
+
}
|
27939
28074
|
};
|
27940
28075
|
}];
|
27941
28076
|
|
@@ -28414,7 +28549,7 @@ var ngCloakDirective = ngDirective({
|
|
28414
28549
|
*
|
28415
28550
|
* This example demonstrates the `controller as` syntax.
|
28416
28551
|
*
|
28417
|
-
* <example name="ngControllerAs">
|
28552
|
+
* <example name="ngControllerAs" module="controllerAsExample">
|
28418
28553
|
* <file name="index.html">
|
28419
28554
|
* <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
|
28420
28555
|
* Name: <input type="text" ng-model="settings.name"/>
|
@@ -28435,6 +28570,9 @@ var ngCloakDirective = ngDirective({
|
|
28435
28570
|
* </div>
|
28436
28571
|
* </file>
|
28437
28572
|
* <file name="app.js">
|
28573
|
+
* angular.module('controllerAsExample', [])
|
28574
|
+
* .controller('SettingsController1', SettingsController1);
|
28575
|
+
*
|
28438
28576
|
* function SettingsController1() {
|
28439
28577
|
* this.name = "John Smith";
|
28440
28578
|
* this.contacts = [
|
@@ -28463,29 +28601,29 @@ var ngCloakDirective = ngDirective({
|
|
28463
28601
|
* <file name="protractor.js" type="protractor">
|
28464
28602
|
* it('should check controller as', function() {
|
28465
28603
|
* var container = element(by.id('ctrl-as-exmpl'));
|
28466
|
-
* expect(container.
|
28604
|
+
* expect(container.element(by.model('settings.name'))
|
28467
28605
|
* .getAttribute('value')).toBe('John Smith');
|
28468
28606
|
*
|
28469
28607
|
* var firstRepeat =
|
28470
|
-
* container.
|
28608
|
+
* container.element(by.repeater('contact in settings.contacts').row(0));
|
28471
28609
|
* var secondRepeat =
|
28472
|
-
* container.
|
28610
|
+
* container.element(by.repeater('contact in settings.contacts').row(1));
|
28473
28611
|
*
|
28474
|
-
* expect(firstRepeat.
|
28612
|
+
* expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
|
28475
28613
|
* .toBe('408 555 1212');
|
28476
28614
|
*
|
28477
|
-
* expect(secondRepeat.
|
28615
|
+
* expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
|
28478
28616
|
* .toBe('john.smith@example.org');
|
28479
28617
|
*
|
28480
|
-
* firstRepeat.
|
28618
|
+
* firstRepeat.element(by.linkText('clear')).click();
|
28481
28619
|
*
|
28482
|
-
* expect(firstRepeat.
|
28620
|
+
* expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
|
28483
28621
|
* .toBe('');
|
28484
28622
|
*
|
28485
|
-
* container.
|
28623
|
+
* container.element(by.linkText('add')).click();
|
28486
28624
|
*
|
28487
|
-
* expect(container.
|
28488
|
-
* .
|
28625
|
+
* expect(container.element(by.repeater('contact in settings.contacts').row(2))
|
28626
|
+
* .element(by.model('contact.value'))
|
28489
28627
|
* .getAttribute('value'))
|
28490
28628
|
* .toBe('yourname@example.org');
|
28491
28629
|
* });
|
@@ -28494,7 +28632,7 @@ var ngCloakDirective = ngDirective({
|
|
28494
28632
|
*
|
28495
28633
|
* This example demonstrates the "attach to `$scope`" style of controller.
|
28496
28634
|
*
|
28497
|
-
* <example name="ngController">
|
28635
|
+
* <example name="ngController" module="controllerExample">
|
28498
28636
|
* <file name="index.html">
|
28499
28637
|
* <div id="ctrl-exmpl" ng-controller="SettingsController2">
|
28500
28638
|
* Name: <input type="text" ng-model="name"/>
|
@@ -28515,6 +28653,9 @@ var ngCloakDirective = ngDirective({
|
|
28515
28653
|
* </div>
|
28516
28654
|
* </file>
|
28517
28655
|
* <file name="app.js">
|
28656
|
+
* angular.module('controllerExample', [])
|
28657
|
+
* .controller('SettingsController2', ['$scope', SettingsController2]);
|
28658
|
+
*
|
28518
28659
|
* function SettingsController2($scope) {
|
28519
28660
|
* $scope.name = "John Smith";
|
28520
28661
|
* $scope.contacts = [
|
@@ -28544,28 +28685,28 @@ var ngCloakDirective = ngDirective({
|
|
28544
28685
|
* it('should check controller', function() {
|
28545
28686
|
* var container = element(by.id('ctrl-exmpl'));
|
28546
28687
|
*
|
28547
|
-
* expect(container.
|
28688
|
+
* expect(container.element(by.model('name'))
|
28548
28689
|
* .getAttribute('value')).toBe('John Smith');
|
28549
28690
|
*
|
28550
28691
|
* var firstRepeat =
|
28551
|
-
* container.
|
28692
|
+
* container.element(by.repeater('contact in contacts').row(0));
|
28552
28693
|
* var secondRepeat =
|
28553
|
-
* container.
|
28694
|
+
* container.element(by.repeater('contact in contacts').row(1));
|
28554
28695
|
*
|
28555
|
-
* expect(firstRepeat.
|
28696
|
+
* expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
|
28556
28697
|
* .toBe('408 555 1212');
|
28557
|
-
* expect(secondRepeat.
|
28698
|
+
* expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
|
28558
28699
|
* .toBe('john.smith@example.org');
|
28559
28700
|
*
|
28560
|
-
* firstRepeat.
|
28701
|
+
* firstRepeat.element(by.linkText('clear')).click();
|
28561
28702
|
*
|
28562
|
-
* expect(firstRepeat.
|
28703
|
+
* expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
|
28563
28704
|
* .toBe('');
|
28564
28705
|
*
|
28565
|
-
* container.
|
28706
|
+
* container.element(by.linkText('add')).click();
|
28566
28707
|
*
|
28567
|
-
* expect(container.
|
28568
|
-
* .
|
28708
|
+
* expect(container.element(by.repeater('contact in contacts').row(2))
|
28709
|
+
* .element(by.model('contact.value'))
|
28569
28710
|
* .getAttribute('value'))
|
28570
28711
|
* .toBe('yourname@example.org');
|
28571
28712
|
* });
|
@@ -28592,8 +28733,10 @@ var ngControllerDirective = [function() {
|
|
28592
28733
|
* This is necessary when developing things like Google Chrome Extensions.
|
28593
28734
|
*
|
28594
28735
|
* CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).
|
28595
|
-
* For
|
28596
|
-
*
|
28736
|
+
* For Angular to be CSP compatible there are only two things that we need to do differently:
|
28737
|
+
*
|
28738
|
+
* - don't use `Function` constructor to generate optimized value getters
|
28739
|
+
* - don't inject custom stylesheet into the document
|
28597
28740
|
*
|
28598
28741
|
* AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp`
|
28599
28742
|
* directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will
|
@@ -28604,7 +28747,18 @@ var ngControllerDirective = [function() {
|
|
28604
28747
|
* includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}).
|
28605
28748
|
* To make those directives work in CSP mode, include the `angular-csp.css` manually.
|
28606
28749
|
*
|
28607
|
-
*
|
28750
|
+
* Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This
|
28751
|
+
* autodetection however triggers a CSP error to be logged in the console:
|
28752
|
+
*
|
28753
|
+
* ```
|
28754
|
+
* Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of
|
28755
|
+
* script in the following Content Security Policy directive: "default-src 'self'". Note that
|
28756
|
+
* 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
|
28757
|
+
* ```
|
28758
|
+
*
|
28759
|
+
* This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`
|
28760
|
+
* directive on the root element of the application or on the `angular.js` script tag, whichever
|
28761
|
+
* appears first in the html document.
|
28608
28762
|
*
|
28609
28763
|
* *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*
|
28610
28764
|
*
|
@@ -28619,9 +28773,9 @@ var ngControllerDirective = [function() {
|
|
28619
28773
|
```
|
28620
28774
|
*/
|
28621
28775
|
|
28622
|
-
// ngCsp is not implemented as a proper directive any more, because we need it be processed while we
|
28623
|
-
// the system (before $parse is instantiated), for this reason we just have
|
28624
|
-
// anywhere in the current doc
|
28776
|
+
// ngCsp is not implemented as a proper directive any more, because we need it be processed while we
|
28777
|
+
// bootstrap the system (before $parse is instantiated), for this reason we just have
|
28778
|
+
// the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc
|
28625
28779
|
|
28626
28780
|
/**
|
28627
28781
|
* @ngdoc directive
|
@@ -28936,21 +29090,22 @@ forEach(
|
|
28936
29090
|
* ({@link guide/expression#-event- Event object is available as `$event`})
|
28937
29091
|
*
|
28938
29092
|
* @example
|
28939
|
-
<example>
|
29093
|
+
<example module="submitExample">
|
28940
29094
|
<file name="index.html">
|
28941
29095
|
<script>
|
28942
|
-
|
28943
|
-
$scope
|
28944
|
-
|
28945
|
-
|
28946
|
-
|
28947
|
-
$scope.
|
28948
|
-
|
28949
|
-
|
28950
|
-
|
28951
|
-
|
29096
|
+
angular.module('submitExample', [])
|
29097
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
29098
|
+
$scope.list = [];
|
29099
|
+
$scope.text = 'hello';
|
29100
|
+
$scope.submit = function() {
|
29101
|
+
if ($scope.text) {
|
29102
|
+
$scope.list.push(this.text);
|
29103
|
+
$scope.text = '';
|
29104
|
+
}
|
29105
|
+
};
|
29106
|
+
}]);
|
28952
29107
|
</script>
|
28953
|
-
<form ng-submit="submit()" ng-controller="
|
29108
|
+
<form ng-submit="submit()" ng-controller="ExampleController">
|
28954
29109
|
Enter text and hit enter:
|
28955
29110
|
<input type="text" ng-model="text" name="text" />
|
28956
29111
|
<input type="submit" id="submit" value="Submit" />
|
@@ -28962,7 +29117,7 @@ forEach(
|
|
28962
29117
|
expect(element(by.binding('list')).getText()).toBe('list=[]');
|
28963
29118
|
element(by.css('#submit')).click();
|
28964
29119
|
expect(element(by.binding('list')).getText()).toContain('hello');
|
28965
|
-
expect(element(by.
|
29120
|
+
expect(element(by.model('text')).getAttribute('value')).toBe('');
|
28966
29121
|
});
|
28967
29122
|
it('should ignore empty strings', function() {
|
28968
29123
|
expect(element(by.binding('list')).getText()).toBe('list=[]');
|
@@ -29235,9 +29390,9 @@ var ngIfDirective = ['$animate', function($animate) {
|
|
29235
29390
|
* - Otherwise enable scrolling only if the expression evaluates to truthy value.
|
29236
29391
|
*
|
29237
29392
|
* @example
|
29238
|
-
<example module="
|
29393
|
+
<example module="includeExample" deps="angular-animate.js" animations="true">
|
29239
29394
|
<file name="index.html">
|
29240
|
-
<div ng-controller="
|
29395
|
+
<div ng-controller="ExampleController">
|
29241
29396
|
<select ng-model="template" ng-options="t.name for t in templates">
|
29242
29397
|
<option value="">(blank)</option>
|
29243
29398
|
</select>
|
@@ -29249,12 +29404,13 @@ var ngIfDirective = ['$animate', function($animate) {
|
|
29249
29404
|
</div>
|
29250
29405
|
</file>
|
29251
29406
|
<file name="script.js">
|
29252
|
-
|
29253
|
-
$scope
|
29254
|
-
|
29255
|
-
{ name: '
|
29256
|
-
|
29257
|
-
|
29407
|
+
angular.module('includeExample', ['ngAnimate'])
|
29408
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
29409
|
+
$scope.templates =
|
29410
|
+
[ { name: 'template1.html', url: 'template1.html'},
|
29411
|
+
{ name: 'template2.html', url: 'template2.html'} ];
|
29412
|
+
$scope.template = $scope.templates[0];
|
29413
|
+
}]);
|
29258
29414
|
</file>
|
29259
29415
|
<file name="template1.html">
|
29260
29416
|
Content of template1.html
|
@@ -29317,7 +29473,7 @@ var ngIfDirective = ['$animate', function($animate) {
|
|
29317
29473
|
return;
|
29318
29474
|
}
|
29319
29475
|
templateSelect.click();
|
29320
|
-
templateSelect.
|
29476
|
+
templateSelect.all(by.css('option')).get(2).click();
|
29321
29477
|
expect(includeElem.getText()).toMatch(/Content of template2.html/);
|
29322
29478
|
});
|
29323
29479
|
|
@@ -29327,7 +29483,7 @@ var ngIfDirective = ['$animate', function($animate) {
|
|
29327
29483
|
return;
|
29328
29484
|
}
|
29329
29485
|
templateSelect.click();
|
29330
|
-
templateSelect.
|
29486
|
+
templateSelect.all(by.css('option')).get(0).click();
|
29331
29487
|
expect(includeElem.isPresent()).toBe(false);
|
29332
29488
|
});
|
29333
29489
|
</file>
|
@@ -29479,14 +29635,15 @@ var ngIncludeFillContentDirective = ['$compile',
|
|
29479
29635
|
* @param {expression} ngInit {@link guide/expression Expression} to eval.
|
29480
29636
|
*
|
29481
29637
|
* @example
|
29482
|
-
<example>
|
29638
|
+
<example module="initExample">
|
29483
29639
|
<file name="index.html">
|
29484
29640
|
<script>
|
29485
|
-
|
29486
|
-
|
29487
|
-
|
29641
|
+
angular.module('initExample', [])
|
29642
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
29643
|
+
$scope.list = [['a', 'b'], ['c', 'd']];
|
29644
|
+
}]);
|
29488
29645
|
</script>
|
29489
|
-
<div ng-controller="
|
29646
|
+
<div ng-controller="ExampleController">
|
29490
29647
|
<div ng-repeat="innerList in list" ng-init="outerIndex = $index">
|
29491
29648
|
<div ng-repeat="value in innerList" ng-init="innerIndex = $index">
|
29492
29649
|
<span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>
|
@@ -29626,7 +29783,7 @@ var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });
|
|
29626
29783
|
* When one person, perhaps John, views the document, "John is viewing" will be shown.
|
29627
29784
|
* When three people view the document, no explicit number rule is found, so
|
29628
29785
|
* an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
|
29629
|
-
* In this case, plural category 'one' is matched and "John,
|
29786
|
+
* In this case, plural category 'one' is matched and "John, Mary and one other person are viewing"
|
29630
29787
|
* is shown.
|
29631
29788
|
*
|
29632
29789
|
* Note that when you specify offsets, you must provide explicit number rules for
|
@@ -29639,16 +29796,17 @@ var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });
|
|
29639
29796
|
* @param {number=} offset Offset to deduct from the total number.
|
29640
29797
|
*
|
29641
29798
|
* @example
|
29642
|
-
<example>
|
29799
|
+
<example module="pluralizeExample">
|
29643
29800
|
<file name="index.html">
|
29644
29801
|
<script>
|
29645
|
-
|
29646
|
-
$scope
|
29647
|
-
|
29648
|
-
|
29649
|
-
|
29802
|
+
angular.module('pluralizeExample', [])
|
29803
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
29804
|
+
$scope.person1 = 'Igor';
|
29805
|
+
$scope.person2 = 'Misko';
|
29806
|
+
$scope.personCount = 1;
|
29807
|
+
}]);
|
29650
29808
|
</script>
|
29651
|
-
<div ng-controller="
|
29809
|
+
<div ng-controller="ExampleController">
|
29652
29810
|
Person 1:<input type="text" ng-model="person1" value="Igor" /><br/>
|
29653
29811
|
Person 2:<input type="text" ng-model="person2" value="Misko" /><br/>
|
29654
29812
|
Number of People:<input type="text" ng-model="personCount" value="1" /><br/>
|
@@ -30508,7 +30666,7 @@ var ngHideDirective = ['$animate', function($animate) {
|
|
30508
30666
|
<file name="protractor.js" type="protractor">
|
30509
30667
|
var colorSpan = element(by.css('span'));
|
30510
30668
|
|
30511
|
-
|
30669
|
+
it('should check ng-style', function() {
|
30512
30670
|
expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
|
30513
30671
|
element(by.css('input[value=\'set color\']')).click();
|
30514
30672
|
expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');
|
@@ -30582,9 +30740,9 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
|
|
30582
30740
|
*
|
30583
30741
|
*
|
30584
30742
|
* @example
|
30585
|
-
<example module="
|
30743
|
+
<example module="switchExample" deps="angular-animate.js" animations="true">
|
30586
30744
|
<file name="index.html">
|
30587
|
-
<div ng-controller="
|
30745
|
+
<div ng-controller="ExampleController">
|
30588
30746
|
<select ng-model="selection" ng-options="item for item in items">
|
30589
30747
|
</select>
|
30590
30748
|
<tt>selection={{selection}}</tt>
|
@@ -30598,10 +30756,11 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
|
|
30598
30756
|
</div>
|
30599
30757
|
</file>
|
30600
30758
|
<file name="script.js">
|
30601
|
-
|
30602
|
-
|
30603
|
-
|
30604
|
-
|
30759
|
+
angular.module('switchExample', ['ngAnimate'])
|
30760
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
30761
|
+
$scope.items = ['settings', 'home', 'other'];
|
30762
|
+
$scope.selection = $scope.items[0];
|
30763
|
+
}]);
|
30605
30764
|
</file>
|
30606
30765
|
<file name="animations.css">
|
30607
30766
|
.animate-switch-container {
|
@@ -30644,11 +30803,11 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
|
|
30644
30803
|
expect(switchElem.getText()).toMatch(/Settings Div/);
|
30645
30804
|
});
|
30646
30805
|
it('should change to home', function() {
|
30647
|
-
select.
|
30806
|
+
select.all(by.css('option')).get(1).click();
|
30648
30807
|
expect(switchElem.getText()).toMatch(/Home Span/);
|
30649
30808
|
});
|
30650
30809
|
it('should select default', function() {
|
30651
|
-
select.
|
30810
|
+
select.all(by.css('option')).get(2).click();
|
30652
30811
|
expect(switchElem.getText()).toMatch(/default/);
|
30653
30812
|
});
|
30654
30813
|
</file>
|
@@ -30740,15 +30899,10 @@ var ngSwitchDefaultDirective = ngDirective({
|
|
30740
30899
|
* @element ANY
|
30741
30900
|
*
|
30742
30901
|
* @example
|
30743
|
-
<example module="
|
30902
|
+
<example module="transcludeExample">
|
30744
30903
|
<file name="index.html">
|
30745
30904
|
<script>
|
30746
|
-
|
30747
|
-
$scope.title = 'Lorem Ipsum';
|
30748
|
-
$scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
|
30749
|
-
}
|
30750
|
-
|
30751
|
-
angular.module('transclude', [])
|
30905
|
+
angular.module('transcludeExample', [])
|
30752
30906
|
.directive('pane', function(){
|
30753
30907
|
return {
|
30754
30908
|
restrict: 'E',
|
@@ -30759,9 +30913,13 @@ var ngSwitchDefaultDirective = ngDirective({
|
|
30759
30913
|
'<div ng-transclude></div>' +
|
30760
30914
|
'</div>'
|
30761
30915
|
};
|
30762
|
-
})
|
30916
|
+
})
|
30917
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
30918
|
+
$scope.title = 'Lorem Ipsum';
|
30919
|
+
$scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
|
30920
|
+
}]);
|
30763
30921
|
</script>
|
30764
|
-
<div ng-controller="
|
30922
|
+
<div ng-controller="ExampleController">
|
30765
30923
|
<input ng-model="title"><br>
|
30766
30924
|
<textarea ng-model="text"></textarea> <br/>
|
30767
30925
|
<pane title="{{title}}">{{text}}</pane>
|
@@ -30920,21 +31078,22 @@ var ngOptionsMinErr = minErr('ngOptions');
|
|
30920
31078
|
* `value` variable (e.g. `value.propertyName`).
|
30921
31079
|
*
|
30922
31080
|
* @example
|
30923
|
-
<example>
|
31081
|
+
<example module="selectExample">
|
30924
31082
|
<file name="index.html">
|
30925
31083
|
<script>
|
30926
|
-
|
30927
|
-
$scope
|
30928
|
-
|
30929
|
-
|
30930
|
-
|
30931
|
-
|
30932
|
-
|
30933
|
-
|
30934
|
-
|
30935
|
-
|
31084
|
+
angular.module('selectExample', [])
|
31085
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
31086
|
+
$scope.colors = [
|
31087
|
+
{name:'black', shade:'dark'},
|
31088
|
+
{name:'white', shade:'light'},
|
31089
|
+
{name:'red', shade:'dark'},
|
31090
|
+
{name:'blue', shade:'dark'},
|
31091
|
+
{name:'yellow', shade:'light'}
|
31092
|
+
];
|
31093
|
+
$scope.myColor = $scope.colors[2]; // red
|
31094
|
+
}]);
|
30936
31095
|
</script>
|
30937
|
-
<div ng-controller="
|
31096
|
+
<div ng-controller="ExampleController">
|
30938
31097
|
<ul>
|
30939
31098
|
<li ng-repeat="color in colors">
|
30940
31099
|
Name: <input ng-model="color.name">
|
@@ -30971,7 +31130,7 @@ var ngOptionsMinErr = minErr('ngOptions');
|
|
30971
31130
|
<file name="protractor.js" type="protractor">
|
30972
31131
|
it('should check ng-options', function() {
|
30973
31132
|
expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');
|
30974
|
-
element.all(by.
|
31133
|
+
element.all(by.model('myColor')).first().click();
|
30975
31134
|
element.all(by.css('select[ng-model="myColor"] option')).first().click();
|
30976
31135
|
expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');
|
30977
31136
|
element(by.css('.nullable select[ng-model="myColor"]')).click();
|
@@ -31387,6 +31546,12 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
31387
31546
|
// lastElement.prop('selected') provided by jQuery has side-effects
|
31388
31547
|
if (existingOption.selected !== option.selected) {
|
31389
31548
|
lastElement.prop('selected', (existingOption.selected = option.selected));
|
31549
|
+
if (msie) {
|
31550
|
+
// See #7692
|
31551
|
+
// The selected item wouldn't visually update on IE without this.
|
31552
|
+
// Tested on Win7: IE9, IE10 and IE11. Future IEs should be tested as well
|
31553
|
+
lastElement.prop('selected', existingOption.selected);
|
31554
|
+
}
|
31390
31555
|
}
|
31391
31556
|
} else {
|
31392
31557
|
// grow elements
|
@@ -31401,7 +31566,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
31401
31566
|
// rather then the element.
|
31402
31567
|
(element = optionTemplate.clone())
|
31403
31568
|
.val(option.id)
|
31404
|
-
.
|
31569
|
+
.prop('selected', option.selected)
|
31405
31570
|
.text(option.label);
|
31406
31571
|
}
|
31407
31572
|
|
@@ -31782,7 +31947,7 @@ _jQuery.fn.bindings = function(windowJquery, bindExp) {
|
|
31782
31947
|
function push(value) {
|
31783
31948
|
if (value === undefined) {
|
31784
31949
|
value = '';
|
31785
|
-
} else if (typeof value
|
31950
|
+
} else if (typeof value !== 'string') {
|
31786
31951
|
value = angular.toJson(value);
|
31787
31952
|
}
|
31788
31953
|
result.push('' + value);
|