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