angularjs-rails 1.2.19 → 1.2.20
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/angularjs-rails/version.rb +2 -2
- data/vendor/assets/javascripts/angular-animate.js +75 -19
- data/vendor/assets/javascripts/angular-cookies.js +17 -15
- data/vendor/assets/javascripts/angular-loader.js +2 -2
- data/vendor/assets/javascripts/angular-mocks.js +1 -1
- data/vendor/assets/javascripts/angular-resource.js +1 -1
- data/vendor/assets/javascripts/angular-route.js +1 -1
- data/vendor/assets/javascripts/angular-sanitize.js +25 -23
- data/vendor/assets/javascripts/angular-scenario.js +505 -461
- data/vendor/assets/javascripts/angular-touch.js +1 -1
- data/vendor/assets/javascripts/angular.js +505 -461
- data/vendor/assets/javascripts/unstable/angular-animate.js +118 -41
- data/vendor/assets/javascripts/unstable/angular-cookies.js +17 -15
- data/vendor/assets/javascripts/unstable/angular-loader.js +2 -2
- data/vendor/assets/javascripts/unstable/angular-messages.js +1 -1
- data/vendor/assets/javascripts/unstable/angular-mocks.js +2 -2
- data/vendor/assets/javascripts/unstable/angular-resource.js +1 -1
- data/vendor/assets/javascripts/unstable/angular-route.js +1 -1
- data/vendor/assets/javascripts/unstable/angular-sanitize.js +25 -23
- data/vendor/assets/javascripts/unstable/angular-scenario.js +980 -759
- data/vendor/assets/javascripts/unstable/angular-touch.js +1 -1
- data/vendor/assets/javascripts/unstable/angular.js +980 -759
- metadata +2 -2
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.3.0-beta.
|
2
|
+
* @license AngularJS v1.3.0-beta.15
|
3
3
|
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -68,7 +68,7 @@ function minErr(module) {
|
|
68
68
|
return match;
|
69
69
|
});
|
70
70
|
|
71
|
-
message = message + '\nhttp://errors.angularjs.org/1.3.0-beta.
|
71
|
+
message = message + '\nhttp://errors.angularjs.org/1.3.0-beta.15/' +
|
72
72
|
(module ? module + '/' : '') + code;
|
73
73
|
for (i = 2; i < arguments.length; i++) {
|
74
74
|
message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
|
@@ -80,89 +80,87 @@ function minErr(module) {
|
|
80
80
|
}
|
81
81
|
|
82
82
|
/* We need to tell jshint what variables are being exported */
|
83
|
-
/* global
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
-hasOwnProperty,
|
165
|
-
|
83
|
+
/* global angular: true,
|
84
|
+
msie: true,
|
85
|
+
jqLite: true,
|
86
|
+
jQuery: true,
|
87
|
+
slice: true,
|
88
|
+
push: true,
|
89
|
+
toString: true,
|
90
|
+
ngMinErr: true,
|
91
|
+
angularModule: true,
|
92
|
+
nodeName_: true,
|
93
|
+
uid: true,
|
94
|
+
REGEX_STRING_REGEXP: true,
|
95
|
+
VALIDITY_STATE_PROPERTY: true,
|
96
|
+
|
97
|
+
lowercase: true,
|
98
|
+
uppercase: true,
|
99
|
+
manualLowercase: true,
|
100
|
+
manualUppercase: true,
|
101
|
+
nodeName_: true,
|
102
|
+
isArrayLike: true,
|
103
|
+
forEach: true,
|
104
|
+
sortedKeys: true,
|
105
|
+
forEachSorted: true,
|
106
|
+
reverseParams: true,
|
107
|
+
nextUid: true,
|
108
|
+
setHashKey: true,
|
109
|
+
extend: true,
|
110
|
+
int: true,
|
111
|
+
inherit: true,
|
112
|
+
noop: true,
|
113
|
+
identity: true,
|
114
|
+
valueFn: true,
|
115
|
+
isUndefined: true,
|
116
|
+
isDefined: true,
|
117
|
+
isObject: true,
|
118
|
+
isString: true,
|
119
|
+
isNumber: true,
|
120
|
+
isDate: true,
|
121
|
+
isArray: true,
|
122
|
+
isFunction: true,
|
123
|
+
isRegExp: true,
|
124
|
+
isWindow: true,
|
125
|
+
isScope: true,
|
126
|
+
isFile: true,
|
127
|
+
isBlob: true,
|
128
|
+
isBoolean: true,
|
129
|
+
trim: true,
|
130
|
+
isElement: true,
|
131
|
+
makeMap: true,
|
132
|
+
map: true,
|
133
|
+
size: true,
|
134
|
+
includes: true,
|
135
|
+
indexOf: true,
|
136
|
+
arrayRemove: true,
|
137
|
+
isLeafNode: true,
|
138
|
+
copy: true,
|
139
|
+
shallowCopy: true,
|
140
|
+
equals: true,
|
141
|
+
csp: true,
|
142
|
+
concat: true,
|
143
|
+
sliceArgs: true,
|
144
|
+
bind: true,
|
145
|
+
toJsonReplacer: true,
|
146
|
+
toJson: true,
|
147
|
+
fromJson: true,
|
148
|
+
startingTag: true,
|
149
|
+
tryDecodeURIComponent: true,
|
150
|
+
parseKeyValue: true,
|
151
|
+
toKeyValue: true,
|
152
|
+
encodeUriSegment: true,
|
153
|
+
encodeUriQuery: true,
|
154
|
+
angularInit: true,
|
155
|
+
bootstrap: true,
|
156
|
+
snake_case: true,
|
157
|
+
bindJQuery: true,
|
158
|
+
assertArg: true,
|
159
|
+
assertArgFn: true,
|
160
|
+
assertNotHasOwnProperty: true,
|
161
|
+
getter: true,
|
162
|
+
getBlockElements: true,
|
163
|
+
hasOwnProperty: true,
|
166
164
|
*/
|
167
165
|
|
168
166
|
////////////////////////////////////
|
@@ -800,9 +798,9 @@ function isLeafNode (node) {
|
|
800
798
|
* @returns {*} The copy or updated `destination`, if `destination` was specified.
|
801
799
|
*
|
802
800
|
* @example
|
803
|
-
<example>
|
801
|
+
<example module="copyExample">
|
804
802
|
<file name="index.html">
|
805
|
-
<div ng-controller="
|
803
|
+
<div ng-controller="ExampleController">
|
806
804
|
<form novalidate class="simple-form">
|
807
805
|
Name: <input type="text" ng-model="user.name" /><br />
|
808
806
|
E-mail: <input type="email" ng-model="user.email" /><br />
|
@@ -816,21 +814,22 @@ function isLeafNode (node) {
|
|
816
814
|
</div>
|
817
815
|
|
818
816
|
<script>
|
819
|
-
|
820
|
-
$scope
|
817
|
+
angular.module('copyExample')
|
818
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
819
|
+
$scope.master= {};
|
821
820
|
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
821
|
+
$scope.update = function(user) {
|
822
|
+
// Example with 1 argument
|
823
|
+
$scope.master= angular.copy(user);
|
824
|
+
};
|
826
825
|
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
826
|
+
$scope.reset = function() {
|
827
|
+
// Example with 2 arguments
|
828
|
+
angular.copy($scope.master, $scope.user);
|
829
|
+
};
|
831
830
|
|
832
|
-
|
833
|
-
|
831
|
+
$scope.reset();
|
832
|
+
}]);
|
834
833
|
</script>
|
835
834
|
</file>
|
836
835
|
</example>
|
@@ -1170,7 +1169,7 @@ function parseKeyValue(/**string*/keyValue) {
|
|
1170
1169
|
key = tryDecodeURIComponent(key_value[0]);
|
1171
1170
|
if ( isDefined(key) ) {
|
1172
1171
|
var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
|
1173
|
-
if (!obj
|
1172
|
+
if (!hasOwnProperty.call(obj, key)) {
|
1174
1173
|
obj[key] = val;
|
1175
1174
|
} else if(isArray(obj[key])) {
|
1176
1175
|
obj[key].push(val);
|
@@ -1968,89 +1967,88 @@ function setupModuleLoader(window) {
|
|
1968
1967
|
|
1969
1968
|
}
|
1970
1969
|
|
1971
|
-
/* global
|
1972
|
-
|
1973
|
-
|
1974
|
-
|
1975
|
-
|
1976
|
-
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
1980
|
-
|
1981
|
-
|
1982
|
-
|
1983
|
-
|
1984
|
-
|
1985
|
-
|
1986
|
-
|
1987
|
-
|
1988
|
-
|
1989
|
-
|
1990
|
-
|
1991
|
-
|
1992
|
-
|
1993
|
-
|
1994
|
-
|
1995
|
-
|
1996
|
-
|
1997
|
-
|
1998
|
-
|
1999
|
-
|
2000
|
-
|
2001
|
-
|
2002
|
-
|
2003
|
-
|
2004
|
-
|
2005
|
-
|
2006
|
-
|
2007
|
-
|
2008
|
-
|
2009
|
-
|
2010
|
-
|
2011
|
-
|
2012
|
-
|
2013
|
-
|
2014
|
-
|
2015
|
-
|
2016
|
-
|
2017
|
-
|
2018
|
-
|
2019
|
-
|
2020
|
-
|
2021
|
-
|
2022
|
-
|
2023
|
-
|
2024
|
-
|
2025
|
-
|
2026
|
-
|
2027
|
-
|
2028
|
-
|
2029
|
-
|
2030
|
-
|
2031
|
-
|
2032
|
-
|
2033
|
-
|
2034
|
-
|
2035
|
-
|
2036
|
-
|
2037
|
-
|
2038
|
-
|
2039
|
-
|
2040
|
-
|
2041
|
-
|
2042
|
-
|
2043
|
-
|
2044
|
-
|
2045
|
-
|
2046
|
-
|
2047
|
-
|
2048
|
-
|
2049
|
-
|
2050
|
-
|
2051
|
-
|
2052
|
-
|
2053
|
-
$WindowProvider
|
1970
|
+
/* global angularModule: true,
|
1971
|
+
version: true,
|
1972
|
+
|
1973
|
+
$LocaleProvider,
|
1974
|
+
$CompileProvider,
|
1975
|
+
|
1976
|
+
htmlAnchorDirective,
|
1977
|
+
inputDirective,
|
1978
|
+
inputDirective,
|
1979
|
+
formDirective,
|
1980
|
+
scriptDirective,
|
1981
|
+
selectDirective,
|
1982
|
+
styleDirective,
|
1983
|
+
optionDirective,
|
1984
|
+
ngBindDirective,
|
1985
|
+
ngBindHtmlDirective,
|
1986
|
+
ngBindTemplateDirective,
|
1987
|
+
ngClassDirective,
|
1988
|
+
ngClassEvenDirective,
|
1989
|
+
ngClassOddDirective,
|
1990
|
+
ngCspDirective,
|
1991
|
+
ngCloakDirective,
|
1992
|
+
ngControllerDirective,
|
1993
|
+
ngFormDirective,
|
1994
|
+
ngHideDirective,
|
1995
|
+
ngIfDirective,
|
1996
|
+
ngIncludeDirective,
|
1997
|
+
ngIncludeFillContentDirective,
|
1998
|
+
ngInitDirective,
|
1999
|
+
ngNonBindableDirective,
|
2000
|
+
ngPluralizeDirective,
|
2001
|
+
ngRepeatDirective,
|
2002
|
+
ngShowDirective,
|
2003
|
+
ngStyleDirective,
|
2004
|
+
ngSwitchDirective,
|
2005
|
+
ngSwitchWhenDirective,
|
2006
|
+
ngSwitchDefaultDirective,
|
2007
|
+
ngOptionsDirective,
|
2008
|
+
ngTranscludeDirective,
|
2009
|
+
ngModelDirective,
|
2010
|
+
ngListDirective,
|
2011
|
+
ngChangeDirective,
|
2012
|
+
patternDirective,
|
2013
|
+
patternDirective,
|
2014
|
+
requiredDirective,
|
2015
|
+
requiredDirective,
|
2016
|
+
minlengthDirective,
|
2017
|
+
minlengthDirective,
|
2018
|
+
maxlengthDirective,
|
2019
|
+
maxlengthDirective,
|
2020
|
+
ngValueDirective,
|
2021
|
+
ngModelOptionsDirective,
|
2022
|
+
ngAttributeAliasDirectives,
|
2023
|
+
ngEventDirectives,
|
2024
|
+
|
2025
|
+
$AnchorScrollProvider,
|
2026
|
+
$AnimateProvider,
|
2027
|
+
$BrowserProvider,
|
2028
|
+
$CacheFactoryProvider,
|
2029
|
+
$ControllerProvider,
|
2030
|
+
$DocumentProvider,
|
2031
|
+
$ExceptionHandlerProvider,
|
2032
|
+
$FilterProvider,
|
2033
|
+
$InterpolateProvider,
|
2034
|
+
$IntervalProvider,
|
2035
|
+
$HttpProvider,
|
2036
|
+
$HttpBackendProvider,
|
2037
|
+
$LocationProvider,
|
2038
|
+
$LogProvider,
|
2039
|
+
$ParseProvider,
|
2040
|
+
$RootScopeProvider,
|
2041
|
+
$QProvider,
|
2042
|
+
$$QProvider,
|
2043
|
+
$$SanitizeUriProvider,
|
2044
|
+
$SceProvider,
|
2045
|
+
$SceDelegateProvider,
|
2046
|
+
$SnifferProvider,
|
2047
|
+
$TemplateCacheProvider,
|
2048
|
+
$TimeoutProvider,
|
2049
|
+
$$RAFProvider,
|
2050
|
+
$$AsyncCallbackProvider,
|
2051
|
+
$WindowProvider
|
2054
2052
|
*/
|
2055
2053
|
|
2056
2054
|
|
@@ -2069,11 +2067,11 @@ function setupModuleLoader(window) {
|
|
2069
2067
|
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
|
2070
2068
|
*/
|
2071
2069
|
var version = {
|
2072
|
-
full: '1.3.0-beta.
|
2070
|
+
full: '1.3.0-beta.15', // all of these placeholder strings will be replaced by grunt's
|
2073
2071
|
major: 1, // package task
|
2074
2072
|
minor: 3,
|
2075
2073
|
dot: 0,
|
2076
|
-
codeName: '
|
2074
|
+
codeName: 'unbelievable-advancement'
|
2077
2075
|
};
|
2078
2076
|
|
2079
2077
|
|
@@ -2205,13 +2203,11 @@ function publishExternalAPI(angular){
|
|
2205
2203
|
]);
|
2206
2204
|
}
|
2207
2205
|
|
2208
|
-
/* global
|
2209
|
-
|
2210
|
-
|
2211
|
-
|
2212
|
-
|
2213
|
-
-BOOLEAN_ATTR,
|
2214
|
-
-ALIASED_ATTR
|
2206
|
+
/* global JQLitePrototype: true,
|
2207
|
+
addEventListenerFn: true,
|
2208
|
+
removeEventListenerFn: true,
|
2209
|
+
BOOLEAN_ATTR: true,
|
2210
|
+
ALIASED_ATTR: true,
|
2215
2211
|
*/
|
2216
2212
|
|
2217
2213
|
//////////////////////////////////
|
@@ -2450,12 +2446,16 @@ function jqLiteClone(element) {
|
|
2450
2446
|
return element.cloneNode(true);
|
2451
2447
|
}
|
2452
2448
|
|
2453
|
-
function jqLiteDealoc(element){
|
2454
|
-
jqLiteRemoveData(element);
|
2455
|
-
|
2456
|
-
|
2457
|
-
|
2458
|
-
|
2449
|
+
function jqLiteDealoc(element, onlyDescendants){
|
2450
|
+
if (!onlyDescendants) jqLiteRemoveData(element);
|
2451
|
+
|
2452
|
+
if (element.childNodes && element.childNodes.length) {
|
2453
|
+
// we use querySelectorAll because documentFragments don't have getElementsByTagName
|
2454
|
+
var descendants = element.getElementsByTagName ? element.getElementsByTagName('*') :
|
2455
|
+
element.querySelectorAll ? element.querySelectorAll('*') : [];
|
2456
|
+
for (var i = 0, l = descendants.length; i < l; i++) {
|
2457
|
+
jqLiteRemoveData(descendants[i]);
|
2458
|
+
}
|
2459
2459
|
}
|
2460
2460
|
}
|
2461
2461
|
|
@@ -2637,9 +2637,7 @@ function jqLiteInheritedData(element, name, value) {
|
|
2637
2637
|
}
|
2638
2638
|
|
2639
2639
|
function jqLiteEmpty(element) {
|
2640
|
-
|
2641
|
-
jqLiteDealoc(childNodes[i]);
|
2642
|
-
}
|
2640
|
+
jqLiteDealoc(element, true);
|
2643
2641
|
while (element.firstChild) {
|
2644
2642
|
element.removeChild(element.firstChild);
|
2645
2643
|
}
|
@@ -2837,9 +2835,7 @@ forEach({
|
|
2837
2835
|
if (isUndefined(value)) {
|
2838
2836
|
return element.innerHTML;
|
2839
2837
|
}
|
2840
|
-
|
2841
|
-
jqLiteDealoc(childNodes[i]);
|
2842
|
-
}
|
2838
|
+
jqLiteDealoc(element, true);
|
2843
2839
|
element.innerHTML = value;
|
2844
2840
|
},
|
2845
2841
|
|
@@ -2959,8 +2955,6 @@ function createEventHandler(element, events) {
|
|
2959
2955
|
forEach({
|
2960
2956
|
removeData: jqLiteRemoveData,
|
2961
2957
|
|
2962
|
-
dealoc: jqLiteDealoc,
|
2963
|
-
|
2964
2958
|
on: function onFn(element, type, fn, unsupported){
|
2965
2959
|
if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
|
2966
2960
|
|
@@ -4112,24 +4106,26 @@ createInjector.$$annotate = annotate;
|
|
4112
4106
|
* This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.
|
4113
4107
|
*
|
4114
4108
|
* @example
|
4115
|
-
<example>
|
4109
|
+
<example module="anchorScrollExample">
|
4116
4110
|
<file name="index.html">
|
4117
|
-
<div id="scrollArea" ng-controller="
|
4111
|
+
<div id="scrollArea" ng-controller="ScrollController">
|
4118
4112
|
<a ng-click="gotoBottom()">Go to bottom</a>
|
4119
4113
|
<a id="bottom"></a> You're at the bottom!
|
4120
4114
|
</div>
|
4121
4115
|
</file>
|
4122
4116
|
<file name="script.js">
|
4123
|
-
|
4124
|
-
$scope
|
4125
|
-
|
4126
|
-
|
4127
|
-
|
4128
|
-
|
4129
|
-
|
4130
|
-
|
4131
|
-
|
4132
|
-
|
4117
|
+
angular.module('anchorScrollExample', [])
|
4118
|
+
.controller('ScrollController', ['$scope', '$location', '$anchorScroll',
|
4119
|
+
function ($scope, $location, $anchorScroll) {
|
4120
|
+
$scope.gotoBottom = function() {
|
4121
|
+
// set the location.hash to the id of
|
4122
|
+
// the element you wish to scroll to.
|
4123
|
+
$location.hash('bottom');
|
4124
|
+
|
4125
|
+
// call $anchorScroll()
|
4126
|
+
$anchorScroll();
|
4127
|
+
};
|
4128
|
+
}]);
|
4133
4129
|
</file>
|
4134
4130
|
<file name="style.css">
|
4135
4131
|
#scrollArea {
|
@@ -4323,6 +4319,7 @@ var $AnimateProvider = ['$provide', function($provide) {
|
|
4323
4319
|
? after.after(element)
|
4324
4320
|
: parent.prepend(element);
|
4325
4321
|
async(done);
|
4322
|
+
return noop;
|
4326
4323
|
},
|
4327
4324
|
|
4328
4325
|
/**
|
@@ -4339,6 +4336,7 @@ var $AnimateProvider = ['$provide', function($provide) {
|
|
4339
4336
|
leave : function(element, done) {
|
4340
4337
|
element.remove();
|
4341
4338
|
async(done);
|
4339
|
+
return noop;
|
4342
4340
|
},
|
4343
4341
|
|
4344
4342
|
/**
|
@@ -4362,7 +4360,7 @@ var $AnimateProvider = ['$provide', function($provide) {
|
|
4362
4360
|
move : function(element, parent, after, done) {
|
4363
4361
|
// Do not remove element before insert. Removing will cause data associated with the
|
4364
4362
|
// element to be dropped. Insert will implicitly do the remove.
|
4365
|
-
this.enter(element, parent, after, done);
|
4363
|
+
return this.enter(element, parent, after, done);
|
4366
4364
|
},
|
4367
4365
|
|
4368
4366
|
/**
|
@@ -4379,13 +4377,14 @@ var $AnimateProvider = ['$provide', function($provide) {
|
|
4379
4377
|
* className value has been added to the element
|
4380
4378
|
*/
|
4381
4379
|
addClass : function(element, className, done) {
|
4382
|
-
className = isString(className)
|
4383
|
-
|
4384
|
-
|
4380
|
+
className = !isString(className)
|
4381
|
+
? (isArray(className) ? className.join(' ') : '')
|
4382
|
+
: className;
|
4385
4383
|
forEach(element, function (element) {
|
4386
4384
|
jqLiteAddClass(element, className);
|
4387
4385
|
});
|
4388
4386
|
async(done);
|
4387
|
+
return noop;
|
4389
4388
|
},
|
4390
4389
|
|
4391
4390
|
/**
|
@@ -4409,6 +4408,7 @@ var $AnimateProvider = ['$provide', function($provide) {
|
|
4409
4408
|
jqLiteRemoveClass(element, className);
|
4410
4409
|
});
|
4411
4410
|
async(done);
|
4411
|
+
return noop;
|
4412
4412
|
},
|
4413
4413
|
|
4414
4414
|
/**
|
@@ -4431,6 +4431,7 @@ var $AnimateProvider = ['$provide', function($provide) {
|
|
4431
4431
|
jqLiteRemoveClass(element, remove);
|
4432
4432
|
});
|
4433
4433
|
async(done);
|
4434
|
+
return noop;
|
4434
4435
|
},
|
4435
4436
|
|
4436
4437
|
enabled : noop
|
@@ -5390,7 +5391,7 @@ function $TemplateCacheProvider() {
|
|
5390
5391
|
* local name. Given `<widget my-attr="count = count + value">` and widget definition of
|
5391
5392
|
* `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
|
5392
5393
|
* a function wrapper for the `count = count + value` expression. Often it's desirable to
|
5393
|
-
* pass data from the isolated scope via an expression
|
5394
|
+
* pass data from the isolated scope via an expression to the parent scope, this can be
|
5394
5395
|
* done by passing a map of local variable names and values into the expression wrapper fn.
|
5395
5396
|
* For example, if the expression is `increment(amount)` then we can specify the amount value
|
5396
5397
|
* by calling the `localFn` as `localFn({amount: 22})`.
|
@@ -5630,10 +5631,10 @@ function $TemplateCacheProvider() {
|
|
5630
5631
|
* to illustrate how `$compile` works.
|
5631
5632
|
* </div>
|
5632
5633
|
*
|
5633
|
-
<example module="
|
5634
|
+
<example module="compileExample">
|
5634
5635
|
<file name="index.html">
|
5635
5636
|
<script>
|
5636
|
-
angular.module('
|
5637
|
+
angular.module('compileExample', [], function($compileProvider) {
|
5637
5638
|
// configure new 'compile' directive by passing a directive
|
5638
5639
|
// factory function. The factory function injects the '$compile'
|
5639
5640
|
$compileProvider.directive('compile', function($compile) {
|
@@ -5657,15 +5658,14 @@ function $TemplateCacheProvider() {
|
|
5657
5658
|
}
|
5658
5659
|
);
|
5659
5660
|
};
|
5660
|
-
})
|
5661
|
-
})
|
5662
|
-
|
5663
|
-
function Ctrl($scope) {
|
5661
|
+
});
|
5662
|
+
})
|
5663
|
+
.controller('GreeterController', ['$scope', function($scope) {
|
5664
5664
|
$scope.name = 'Angular';
|
5665
5665
|
$scope.html = 'Hello {{name}}';
|
5666
|
-
}
|
5666
|
+
}]);
|
5667
5667
|
</script>
|
5668
|
-
<div ng-controller="
|
5668
|
+
<div ng-controller="GreeterController">
|
5669
5669
|
<input ng-model="name"> <br>
|
5670
5670
|
<textarea ng-model="html"></textarea> <br>
|
5671
5671
|
<div compile="html"></div>
|
@@ -6093,14 +6093,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
6093
6093
|
$linkNode.data('$' + name + 'Controller', instance);
|
6094
6094
|
});
|
6095
6095
|
|
6096
|
-
|
6097
|
-
for(var i = 0, ii = $linkNode.length; i<ii; i++) {
|
6098
|
-
var node = $linkNode[i],
|
6099
|
-
nodeType = node.nodeType;
|
6100
|
-
if (nodeType === 1 /* element */ || nodeType === 9 /* document */) {
|
6101
|
-
$linkNode.eq(i).data('$scope', scope);
|
6102
|
-
}
|
6103
|
-
}
|
6096
|
+
$linkNode.data('$scope', scope);
|
6104
6097
|
|
6105
6098
|
if (cloneConnectFn) cloneConnectFn($linkNode, scope);
|
6106
6099
|
if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);
|
@@ -7356,6 +7349,7 @@ function tokenDifference(str1, str2) {
|
|
7356
7349
|
*/
|
7357
7350
|
function $ControllerProvider() {
|
7358
7351
|
var controllers = {},
|
7352
|
+
globals = false,
|
7359
7353
|
CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
|
7360
7354
|
|
7361
7355
|
|
@@ -7376,6 +7370,15 @@ function $ControllerProvider() {
|
|
7376
7370
|
}
|
7377
7371
|
};
|
7378
7372
|
|
7373
|
+
/**
|
7374
|
+
* @ngdoc method
|
7375
|
+
* @name $controllerProvider#allowGlobals
|
7376
|
+
* @description If called, allows `$controller` to find controller constructors on `window`
|
7377
|
+
*/
|
7378
|
+
this.allowGlobals = function() {
|
7379
|
+
globals = true;
|
7380
|
+
};
|
7381
|
+
|
7379
7382
|
|
7380
7383
|
this.$get = ['$injector', '$window', function($injector, $window) {
|
7381
7384
|
|
@@ -7390,7 +7393,8 @@ function $ControllerProvider() {
|
|
7390
7393
|
*
|
7391
7394
|
* * check if a controller with given name is registered via `$controllerProvider`
|
7392
7395
|
* * check if evaluating the string on the current scope returns a constructor
|
7393
|
-
* * check `window[constructor]` on the global
|
7396
|
+
* * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
|
7397
|
+
* `window` object (not recommended)
|
7394
7398
|
*
|
7395
7399
|
* @param {Object} locals Injection locals for Controller.
|
7396
7400
|
* @return {Object} Instance of given controller.
|
@@ -7410,7 +7414,8 @@ function $ControllerProvider() {
|
|
7410
7414
|
identifier = match[3];
|
7411
7415
|
expression = controllers.hasOwnProperty(constructor)
|
7412
7416
|
? controllers[constructor]
|
7413
|
-
: getter(locals.$scope, constructor, true) ||
|
7417
|
+
: getter(locals.$scope, constructor, true) ||
|
7418
|
+
(globals ? getter($window, constructor, true) : undefined);
|
7414
7419
|
|
7415
7420
|
assertArgFn(expression, constructor, true);
|
7416
7421
|
}
|
@@ -7441,18 +7446,19 @@ function $ControllerProvider() {
|
|
7441
7446
|
* A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.
|
7442
7447
|
*
|
7443
7448
|
* @example
|
7444
|
-
<example>
|
7449
|
+
<example module="documentExample">
|
7445
7450
|
<file name="index.html">
|
7446
|
-
<div ng-controller="
|
7451
|
+
<div ng-controller="ExampleController">
|
7447
7452
|
<p>$document title: <b ng-bind="title"></b></p>
|
7448
7453
|
<p>window.document title: <b ng-bind="windowTitle"></b></p>
|
7449
7454
|
</div>
|
7450
7455
|
</file>
|
7451
7456
|
<file name="script.js">
|
7452
|
-
|
7453
|
-
$scope
|
7454
|
-
|
7455
|
-
|
7457
|
+
angular.module('documentExample', [])
|
7458
|
+
.controller('ExampleController', ['$scope', '$document', function($scope, $document) {
|
7459
|
+
$scope.title = $document[0].title;
|
7460
|
+
$scope.windowTitle = angular.element(window.document)[0].title;
|
7461
|
+
}]);
|
7456
7462
|
</file>
|
7457
7463
|
</example>
|
7458
7464
|
*/
|
@@ -7585,12 +7591,39 @@ function isSuccess(status) {
|
|
7585
7591
|
}
|
7586
7592
|
|
7587
7593
|
|
7594
|
+
/**
|
7595
|
+
* @ngdoc provider
|
7596
|
+
* @name $httpProvider
|
7597
|
+
* @description
|
7598
|
+
* Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
|
7599
|
+
* */
|
7588
7600
|
function $HttpProvider() {
|
7589
7601
|
var JSON_START = /^\s*(\[|\{[^\{])/,
|
7590
7602
|
JSON_END = /[\}\]]\s*$/,
|
7591
7603
|
PROTECTION_PREFIX = /^\)\]\}',?\n/,
|
7592
7604
|
CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': 'application/json;charset=utf-8'};
|
7593
7605
|
|
7606
|
+
/**
|
7607
|
+
* @ngdoc property
|
7608
|
+
* @name $httpProvider#defaults
|
7609
|
+
* @description
|
7610
|
+
*
|
7611
|
+
* Object containing default values for all {@link ng.$http $http} requests.
|
7612
|
+
*
|
7613
|
+
* - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
|
7614
|
+
* Defaults value is `'XSRF-TOKEN'`.
|
7615
|
+
*
|
7616
|
+
* - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
|
7617
|
+
* XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
|
7618
|
+
*
|
7619
|
+
* - **`defaults.headers`** - {Object} - Default headers for all $http requests.
|
7620
|
+
* Refer to {@link ng.$http#setting-http-headers $http} for documentation on
|
7621
|
+
* setting default headers.
|
7622
|
+
* - **`defaults.headers.common`**
|
7623
|
+
* - **`defaults.headers.post`**
|
7624
|
+
* - **`defaults.headers.put`**
|
7625
|
+
* - **`defaults.headers.patch`**
|
7626
|
+
**/
|
7594
7627
|
var defaults = this.defaults = {
|
7595
7628
|
// transform incoming response data
|
7596
7629
|
transformResponse: [function(data) {
|
@@ -8008,9 +8041,9 @@ function $HttpProvider() {
|
|
8008
8041
|
*
|
8009
8042
|
*
|
8010
8043
|
* @example
|
8011
|
-
<example>
|
8044
|
+
<example module="httpExample">
|
8012
8045
|
<file name="index.html">
|
8013
|
-
<div ng-controller="
|
8046
|
+
<div ng-controller="FetchController">
|
8014
8047
|
<select ng-model="method">
|
8015
8048
|
<option>GET</option>
|
8016
8049
|
<option>JSONP</option>
|
@@ -8032,30 +8065,32 @@ function $HttpProvider() {
|
|
8032
8065
|
</div>
|
8033
8066
|
</file>
|
8034
8067
|
<file name="script.js">
|
8035
|
-
|
8036
|
-
$scope
|
8037
|
-
|
8038
|
-
|
8039
|
-
|
8040
|
-
|
8041
|
-
|
8042
|
-
|
8043
|
-
|
8044
|
-
|
8045
|
-
$scope.
|
8046
|
-
|
8047
|
-
|
8048
|
-
|
8049
|
-
|
8050
|
-
|
8051
|
-
|
8052
|
-
|
8068
|
+
angular.module('httpExample', [])
|
8069
|
+
.controller('FetchController', ['$scope', '$http', '$templateCache',
|
8070
|
+
function($scope, $http, $templateCache) {
|
8071
|
+
$scope.method = 'GET';
|
8072
|
+
$scope.url = 'http-hello.html';
|
8073
|
+
|
8074
|
+
$scope.fetch = function() {
|
8075
|
+
$scope.code = null;
|
8076
|
+
$scope.response = null;
|
8077
|
+
|
8078
|
+
$http({method: $scope.method, url: $scope.url, cache: $templateCache}).
|
8079
|
+
success(function(data, status) {
|
8080
|
+
$scope.status = status;
|
8081
|
+
$scope.data = data;
|
8082
|
+
}).
|
8083
|
+
error(function(data, status) {
|
8084
|
+
$scope.data = data || "Request failed";
|
8085
|
+
$scope.status = status;
|
8086
|
+
});
|
8087
|
+
};
|
8053
8088
|
|
8054
|
-
|
8055
|
-
|
8056
|
-
|
8057
|
-
|
8058
|
-
|
8089
|
+
$scope.updateModel = function(method, url) {
|
8090
|
+
$scope.method = method;
|
8091
|
+
$scope.url = url;
|
8092
|
+
};
|
8093
|
+
}]);
|
8059
8094
|
</file>
|
8060
8095
|
<file name="http-hello.html">
|
8061
8096
|
Hello, $http!
|
@@ -8109,7 +8144,7 @@ function $HttpProvider() {
|
|
8109
8144
|
var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);
|
8110
8145
|
|
8111
8146
|
// strip content-type if data is undefined
|
8112
|
-
if (isUndefined(
|
8147
|
+
if (isUndefined(reqData)) {
|
8113
8148
|
forEach(headers, function(value, header) {
|
8114
8149
|
if (lowercase(header) === 'content-type') {
|
8115
8150
|
delete headers[header];
|
@@ -8178,10 +8213,6 @@ function $HttpProvider() {
|
|
8178
8213
|
|
8179
8214
|
defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
|
8180
8215
|
|
8181
|
-
// execute if header value is function
|
8182
|
-
execHeaders(defHeaders);
|
8183
|
-
execHeaders(reqHeaders);
|
8184
|
-
|
8185
8216
|
// using for-in instead of forEach to avoid unecessary iteration after header has been found
|
8186
8217
|
defaultHeadersIteration:
|
8187
8218
|
for (defHeaderName in defHeaders) {
|
@@ -8196,6 +8227,8 @@ function $HttpProvider() {
|
|
8196
8227
|
reqHeaders[defHeaderName] = defHeaders[defHeaderName];
|
8197
8228
|
}
|
8198
8229
|
|
8230
|
+
// execute if header value is a function for merged headers
|
8231
|
+
execHeaders(reqHeaders);
|
8199
8232
|
return reqHeaders;
|
8200
8233
|
|
8201
8234
|
function execHeaders(headers) {
|
@@ -9103,25 +9136,27 @@ function $IntervalProvider() {
|
|
9103
9136
|
* @returns {promise} A promise which will be notified on each iteration.
|
9104
9137
|
*
|
9105
9138
|
* @example
|
9106
|
-
* <example module="
|
9107
|
-
*
|
9108
|
-
*
|
9109
|
-
*
|
9110
|
-
*
|
9111
|
-
* $scope
|
9112
|
-
*
|
9139
|
+
* <example module="intervalExample">
|
9140
|
+
* <file name="index.html">
|
9141
|
+
* <script>
|
9142
|
+
* angular.module('intervalExample', [])
|
9143
|
+
* .controller('ExampleController', ['$scope', '$interval',
|
9144
|
+
* function($scope, $interval) {
|
9145
|
+
* $scope.format = 'M/d/yy h:mm:ss a';
|
9146
|
+
* $scope.blood_1 = 100;
|
9147
|
+
* $scope.blood_2 = 120;
|
9113
9148
|
*
|
9114
|
-
*
|
9115
|
-
*
|
9116
|
-
*
|
9117
|
-
*
|
9149
|
+
* var stop;
|
9150
|
+
* $scope.fight = function() {
|
9151
|
+
* // Don't start a new fight if we are already fighting
|
9152
|
+
* if ( angular.isDefined(stop) ) return;
|
9118
9153
|
*
|
9119
9154
|
* stop = $interval(function() {
|
9120
9155
|
* if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
|
9121
|
-
*
|
9122
|
-
*
|
9156
|
+
* $scope.blood_1 = $scope.blood_1 - 3;
|
9157
|
+
* $scope.blood_2 = $scope.blood_2 - 4;
|
9123
9158
|
* } else {
|
9124
|
-
*
|
9159
|
+
* $scope.stopFight();
|
9125
9160
|
* }
|
9126
9161
|
* }, 100);
|
9127
9162
|
* };
|
@@ -9136,22 +9171,21 @@ function $IntervalProvider() {
|
|
9136
9171
|
* $scope.resetFight = function() {
|
9137
9172
|
* $scope.blood_1 = 100;
|
9138
9173
|
* $scope.blood_2 = 120;
|
9139
|
-
* }
|
9174
|
+
* };
|
9140
9175
|
*
|
9141
9176
|
* $scope.$on('$destroy', function() {
|
9142
|
-
* // Make sure that the interval
|
9177
|
+
* // Make sure that the interval nis destroyed too
|
9143
9178
|
* $scope.stopFight();
|
9144
9179
|
* });
|
9145
|
-
* }
|
9146
|
-
*
|
9147
|
-
*
|
9148
|
-
*
|
9149
|
-
*
|
9150
|
-
* .directive('myCurrentTime', function($interval, dateFilter) {
|
9180
|
+
* })
|
9181
|
+
* // Register the 'myCurrentTime' directive factory method.
|
9182
|
+
* // We inject $interval and dateFilter service since the factory method is DI.
|
9183
|
+
* .directive('myCurrentTime', ['$interval', 'dateFilter',
|
9184
|
+
* function($interval, dateFilter) {
|
9151
9185
|
* // return the directive link function. (compile function not needed)
|
9152
9186
|
* return function(scope, element, attrs) {
|
9153
9187
|
* var format, // date format
|
9154
|
-
*
|
9188
|
+
* stopTime; // so that we can cancel the time updates
|
9155
9189
|
*
|
9156
9190
|
* // used to update the UI
|
9157
9191
|
* function updateTime() {
|
@@ -9167,28 +9201,28 @@ function $IntervalProvider() {
|
|
9167
9201
|
* stopTime = $interval(updateTime, 1000);
|
9168
9202
|
*
|
9169
9203
|
* // listen on DOM destroy (removal) event, and cancel the next UI update
|
9170
|
-
* // to prevent updating time
|
9204
|
+
* // to prevent updating time after the DOM element was removed.
|
9171
9205
|
* element.on('$destroy', function() {
|
9172
9206
|
* $interval.cancel(stopTime);
|
9173
9207
|
* });
|
9174
9208
|
* }
|
9175
9209
|
* });
|
9176
|
-
*
|
9210
|
+
* </script>
|
9177
9211
|
*
|
9178
|
-
*
|
9179
|
-
*
|
9180
|
-
*
|
9181
|
-
*
|
9182
|
-
*
|
9183
|
-
*
|
9184
|
-
*
|
9185
|
-
*
|
9186
|
-
*
|
9187
|
-
*
|
9188
|
-
* </div>
|
9212
|
+
* <div>
|
9213
|
+
* <div ng-controller="ExampleController">
|
9214
|
+
* Date format: <input ng-model="format"> <hr/>
|
9215
|
+
* Current time is: <span my-current-time="format"></span>
|
9216
|
+
* <hr/>
|
9217
|
+
* Blood 1 : <font color='red'>{{blood_1}}</font>
|
9218
|
+
* Blood 2 : <font color='red'>{{blood_2}}</font>
|
9219
|
+
* <button type="button" data-ng-click="fight()">Fight</button>
|
9220
|
+
* <button type="button" data-ng-click="stopFight()">StopFight</button>
|
9221
|
+
* <button type="button" data-ng-click="resetFight()">resetFight</button>
|
9189
9222
|
* </div>
|
9223
|
+
* </div>
|
9190
9224
|
*
|
9191
|
-
*
|
9225
|
+
* </file>
|
9192
9226
|
* </example>
|
9193
9227
|
*/
|
9194
9228
|
function interval(fn, delay, count, invokeApply) {
|
@@ -9745,14 +9779,17 @@ LocationHashbangInHtml5Url.prototype =
|
|
9745
9779
|
* If the argument is a hash object containing an array of values, these values will be encoded
|
9746
9780
|
* as duplicate search parameters in the url.
|
9747
9781
|
*
|
9748
|
-
* @param {(string|Array<string
|
9749
|
-
* override only a single search property.
|
9782
|
+
* @param {(string|Array<string>|boolean)=} paramValue If `search` is a string, then `paramValue`
|
9783
|
+
* will override only a single search property.
|
9750
9784
|
*
|
9751
9785
|
* If `paramValue` is an array, it will override the property of the `search` component of
|
9752
9786
|
* `$location` specified via the first argument.
|
9753
9787
|
*
|
9754
9788
|
* If `paramValue` is `null`, the property specified via the first argument will be deleted.
|
9755
9789
|
*
|
9790
|
+
* If `paramValue` is `true`, the property specified via the first argument will be added with no
|
9791
|
+
* value nor trailing equal sign.
|
9792
|
+
*
|
9756
9793
|
* @return {Object} If called with no arguments returns the parsed `search` object. If called with
|
9757
9794
|
* one or more arguments returns `$location` object itself.
|
9758
9795
|
*/
|
@@ -9764,6 +9801,11 @@ LocationHashbangInHtml5Url.prototype =
|
|
9764
9801
|
if (isString(search)) {
|
9765
9802
|
this.$$search = parseKeyValue(search);
|
9766
9803
|
} else if (isObject(search)) {
|
9804
|
+
// remove object undefined or null properties
|
9805
|
+
forEach(search, function(value, key) {
|
9806
|
+
if (value == null) delete search[key];
|
9807
|
+
});
|
9808
|
+
|
9767
9809
|
this.$$search = search;
|
9768
9810
|
} else {
|
9769
9811
|
throw $locationMinErr('isrcharg',
|
@@ -10085,15 +10127,16 @@ function $LocationProvider(){
|
|
10085
10127
|
* {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.
|
10086
10128
|
*
|
10087
10129
|
* @example
|
10088
|
-
<example>
|
10130
|
+
<example module="logExample">
|
10089
10131
|
<file name="script.js">
|
10090
|
-
|
10091
|
-
$scope
|
10092
|
-
|
10093
|
-
|
10132
|
+
angular.module('logExample', [])
|
10133
|
+
.controller('LogController', ['$scope', '$log', function($scope, $log) {
|
10134
|
+
$scope.$log = $log;
|
10135
|
+
$scope.message = 'Hello World!';
|
10136
|
+
}]);
|
10094
10137
|
</file>
|
10095
10138
|
<file name="index.html">
|
10096
|
-
<div ng-controller="
|
10139
|
+
<div ng-controller="LogController">
|
10097
10140
|
<p>Reload this page with open console, enter text and hit the log button...</p>
|
10098
10141
|
Message:
|
10099
10142
|
<input type="text" ng-model="message"/>
|
@@ -10117,7 +10160,7 @@ function $LogProvider(){
|
|
10117
10160
|
self = this;
|
10118
10161
|
|
10119
10162
|
/**
|
10120
|
-
* @ngdoc
|
10163
|
+
* @ngdoc method
|
10121
10164
|
* @name $logProvider#debugEnabled
|
10122
10165
|
* @description
|
10123
10166
|
* @param {boolean=} flag enable or disable debug level messages
|
@@ -11106,26 +11149,6 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp) {
|
|
11106
11149
|
};
|
11107
11150
|
}
|
11108
11151
|
|
11109
|
-
function simpleGetterFn1(key0, fullExp) {
|
11110
|
-
ensureSafeMemberName(key0, fullExp);
|
11111
|
-
|
11112
|
-
return function simpleGetterFn1(scope, locals) {
|
11113
|
-
if (scope == null) return undefined;
|
11114
|
-
return ((locals && locals.hasOwnProperty(key0)) ? locals : scope)[key0];
|
11115
|
-
};
|
11116
|
-
}
|
11117
|
-
|
11118
|
-
function simpleGetterFn2(key0, key1, fullExp) {
|
11119
|
-
ensureSafeMemberName(key0, fullExp);
|
11120
|
-
ensureSafeMemberName(key1, fullExp);
|
11121
|
-
|
11122
|
-
return function simpleGetterFn2(scope, locals) {
|
11123
|
-
if (scope == null) return undefined;
|
11124
|
-
scope = ((locals && locals.hasOwnProperty(key0)) ? locals : scope)[key0];
|
11125
|
-
return scope == null ? undefined : scope[key1];
|
11126
|
-
};
|
11127
|
-
}
|
11128
|
-
|
11129
11152
|
function getterFn(path, options, fullExp) {
|
11130
11153
|
// Check whether the cache has this getter already.
|
11131
11154
|
// We can use hasOwnProperty directly on the cache because we ensure,
|
@@ -11138,13 +11161,8 @@ function getterFn(path, options, fullExp) {
|
|
11138
11161
|
pathKeysLength = pathKeys.length,
|
11139
11162
|
fn;
|
11140
11163
|
|
11141
|
-
// When we have only 1 or 2 tokens, use optimized special case closures.
|
11142
11164
|
// http://jsperf.com/angularjs-parse-getter/6
|
11143
|
-
if (
|
11144
|
-
fn = simpleGetterFn1(pathKeys[0], fullExp);
|
11145
|
-
} else if (pathKeysLength === 2) {
|
11146
|
-
fn = simpleGetterFn2(pathKeys[0], pathKeys[1], fullExp);
|
11147
|
-
} else if (options.csp) {
|
11165
|
+
if (options.csp) {
|
11148
11166
|
if (pathKeysLength < 6) {
|
11149
11167
|
fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp);
|
11150
11168
|
} else {
|
@@ -13282,19 +13300,21 @@ function adjustMatchers(matchers) {
|
|
13282
13300
|
*
|
13283
13301
|
* Here is what a secure configuration for this scenario might look like:
|
13284
13302
|
*
|
13285
|
-
*
|
13286
|
-
*
|
13287
|
-
*
|
13288
|
-
*
|
13289
|
-
*
|
13290
|
-
*
|
13291
|
-
*
|
13292
|
-
*
|
13293
|
-
*
|
13294
|
-
*
|
13295
|
-
*
|
13296
|
-
*
|
13297
|
-
*
|
13303
|
+
* ```
|
13304
|
+
* angular.module('myApp', []).config(function($sceDelegateProvider) {
|
13305
|
+
* $sceDelegateProvider.resourceUrlWhitelist([
|
13306
|
+
* // Allow same origin resource loads.
|
13307
|
+
* 'self',
|
13308
|
+
* // Allow loading from our assets domain. Notice the difference between * and **.
|
13309
|
+
* 'http://srv*.assets.example.com/**'
|
13310
|
+
* ]);
|
13311
|
+
*
|
13312
|
+
* // The blacklist overrides the whitelist so the open redirect here is blocked.
|
13313
|
+
* $sceDelegateProvider.resourceUrlBlacklist([
|
13314
|
+
* 'http://myapp.example.com/clickThru**'
|
13315
|
+
* ]);
|
13316
|
+
* });
|
13317
|
+
* ```
|
13298
13318
|
*/
|
13299
13319
|
|
13300
13320
|
function $SceDelegateProvider() {
|
@@ -13589,10 +13609,10 @@ function $SceDelegateProvider() {
|
|
13589
13609
|
*
|
13590
13610
|
* Here's an example of a binding in a privileged context:
|
13591
13611
|
*
|
13592
|
-
*
|
13593
|
-
*
|
13594
|
-
*
|
13595
|
-
*
|
13612
|
+
* ```
|
13613
|
+
* <input ng-model="userHtml">
|
13614
|
+
* <div ng-bind-html="userHtml"></div>
|
13615
|
+
* ```
|
13596
13616
|
*
|
13597
13617
|
* Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE
|
13598
13618
|
* disabled, this application allows the user to render arbitrary HTML into the DIV.
|
@@ -13632,15 +13652,15 @@ function $SceDelegateProvider() {
|
|
13632
13652
|
* ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly
|
13633
13653
|
* simplified):
|
13634
13654
|
*
|
13635
|
-
*
|
13636
|
-
*
|
13637
|
-
*
|
13638
|
-
*
|
13639
|
-
*
|
13640
|
-
*
|
13641
|
-
*
|
13642
|
-
*
|
13643
|
-
*
|
13655
|
+
* ```
|
13656
|
+
* var ngBindHtmlDirective = ['$sce', function($sce) {
|
13657
|
+
* return function(scope, element, attr) {
|
13658
|
+
* scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
|
13659
|
+
* element.html(value || '');
|
13660
|
+
* });
|
13661
|
+
* };
|
13662
|
+
* }];
|
13663
|
+
* ```
|
13644
13664
|
*
|
13645
13665
|
* ## Impact on loading templates
|
13646
13666
|
*
|
@@ -13744,66 +13764,65 @@ function $SceDelegateProvider() {
|
|
13744
13764
|
*
|
13745
13765
|
* ## Show me an example using SCE.
|
13746
13766
|
*
|
13747
|
-
*
|
13748
|
-
<
|
13749
|
-
<
|
13750
|
-
|
13751
|
-
|
13752
|
-
|
13753
|
-
|
13754
|
-
|
13755
|
-
|
13756
|
-
|
13757
|
-
|
13758
|
-
|
13759
|
-
|
13760
|
-
|
13761
|
-
|
13762
|
-
|
13763
|
-
|
13764
|
-
|
13765
|
-
|
13766
|
-
|
13767
|
-
|
13768
|
-
|
13769
|
-
|
13770
|
-
|
13771
|
-
|
13772
|
-
|
13773
|
-
|
13774
|
-
|
13775
|
-
|
13776
|
-
|
13777
|
-
|
13778
|
-
|
13779
|
-
|
13780
|
-
|
13781
|
-
|
13782
|
-
|
13783
|
-
|
13784
|
-
|
13785
|
-
|
13786
|
-
|
13787
|
-
|
13788
|
-
|
13789
|
-
|
13790
|
-
|
13791
|
-
|
13792
|
-
|
13793
|
-
|
13794
|
-
|
13795
|
-
|
13796
|
-
|
13797
|
-
|
13798
|
-
|
13799
|
-
|
13800
|
-
|
13801
|
-
|
13802
|
-
|
13803
|
-
|
13804
|
-
|
13805
|
-
</
|
13806
|
-
</example>
|
13767
|
+
* <example module="mySceApp" deps="angular-sanitize.js">
|
13768
|
+
* <file name="index.html">
|
13769
|
+
* <div ng-controller="AppController as myCtrl">
|
13770
|
+
* <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
|
13771
|
+
* <b>User comments</b><br>
|
13772
|
+
* By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
|
13773
|
+
* $sanitize is available. If $sanitize isn't available, this results in an error instead of an
|
13774
|
+
* exploit.
|
13775
|
+
* <div class="well">
|
13776
|
+
* <div ng-repeat="userComment in myCtrl.userComments">
|
13777
|
+
* <b>{{userComment.name}}</b>:
|
13778
|
+
* <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
|
13779
|
+
* <br>
|
13780
|
+
* </div>
|
13781
|
+
* </div>
|
13782
|
+
* </div>
|
13783
|
+
* </file>
|
13784
|
+
*
|
13785
|
+
* <file name="script.js">
|
13786
|
+
* angular.module('mySceApp', ['ngSanitize'])
|
13787
|
+
* .controller('AppController', ['$http', '$templateCache', '$sce',
|
13788
|
+
* function($http, $templateCache, $sce) {
|
13789
|
+
* var self = this;
|
13790
|
+
* $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
|
13791
|
+
* self.userComments = userComments;
|
13792
|
+
* });
|
13793
|
+
* self.explicitlyTrustedHtml = $sce.trustAsHtml(
|
13794
|
+
* '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' +
|
13795
|
+
* 'sanitization."">Hover over this text.</span>');
|
13796
|
+
* }]);
|
13797
|
+
* </file>
|
13798
|
+
*
|
13799
|
+
* <file name="test_data.json">
|
13800
|
+
* [
|
13801
|
+
* { "name": "Alice",
|
13802
|
+
* "htmlComment":
|
13803
|
+
* "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
|
13804
|
+
* },
|
13805
|
+
* { "name": "Bob",
|
13806
|
+
* "htmlComment": "<i>Yes!</i> Am I the only other one?"
|
13807
|
+
* }
|
13808
|
+
* ]
|
13809
|
+
* </file>
|
13810
|
+
*
|
13811
|
+
* <file name="protractor.js" type="protractor">
|
13812
|
+
* describe('SCE doc demo', function() {
|
13813
|
+
* it('should sanitize untrusted values', function() {
|
13814
|
+
* expect(element.all(by.css('.htmlComment')).first().getInnerHtml())
|
13815
|
+
* .toBe('<span>Is <i>anyone</i> reading this?</span>');
|
13816
|
+
* });
|
13817
|
+
*
|
13818
|
+
* it('should NOT sanitize explicitly trusted values', function() {
|
13819
|
+
* expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(
|
13820
|
+
* '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' +
|
13821
|
+
* 'sanitization."">Hover over this text.</span>');
|
13822
|
+
* });
|
13823
|
+
* });
|
13824
|
+
* </file>
|
13825
|
+
* </example>
|
13807
13826
|
*
|
13808
13827
|
*
|
13809
13828
|
*
|
@@ -13817,13 +13836,13 @@ function $SceDelegateProvider() {
|
|
13817
13836
|
*
|
13818
13837
|
* That said, here's how you can completely disable SCE:
|
13819
13838
|
*
|
13820
|
-
*
|
13821
|
-
*
|
13822
|
-
*
|
13823
|
-
*
|
13824
|
-
*
|
13825
|
-
*
|
13826
|
-
*
|
13839
|
+
* ```
|
13840
|
+
* angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
|
13841
|
+
* // Completely disable SCE. For demonstration purposes only!
|
13842
|
+
* // Do not use in new projects.
|
13843
|
+
* $sceProvider.enabled(false);
|
13844
|
+
* });
|
13845
|
+
* ```
|
13827
13846
|
*
|
13828
13847
|
*/
|
13829
13848
|
/* jshint maxlen: 100 */
|
@@ -14522,17 +14541,18 @@ function urlIsSameOrigin(requestUrl) {
|
|
14522
14541
|
* expression.
|
14523
14542
|
*
|
14524
14543
|
* @example
|
14525
|
-
<example>
|
14544
|
+
<example module="windowExample">
|
14526
14545
|
<file name="index.html">
|
14527
14546
|
<script>
|
14528
|
-
|
14529
|
-
$scope
|
14530
|
-
|
14547
|
+
angular.module('windowExample', [])
|
14548
|
+
.controller('ExampleController', ['$scope', '$window', function ($scope, $window) {
|
14549
|
+
$scope.greeting = 'Hello, World!';
|
14550
|
+
$scope.doGreeting = function(greeting) {
|
14531
14551
|
$window.alert(greeting);
|
14532
|
-
|
14533
|
-
|
14552
|
+
};
|
14553
|
+
}]);
|
14534
14554
|
</script>
|
14535
|
-
<div ng-controller="
|
14555
|
+
<div ng-controller="ExampleController">
|
14536
14556
|
<input type="text" ng-model="greeting" />
|
14537
14557
|
<button ng-click="doGreeting(greeting)">ALERT</button>
|
14538
14558
|
</div>
|
@@ -14550,6 +14570,17 @@ function $WindowProvider(){
|
|
14550
14570
|
this.$get = valueFn(window);
|
14551
14571
|
}
|
14552
14572
|
|
14573
|
+
/* global currencyFilter: true,
|
14574
|
+
dateFilter: true,
|
14575
|
+
filterFilter: true,
|
14576
|
+
jsonFilter: true,
|
14577
|
+
limitToFilter: true,
|
14578
|
+
lowercaseFilter: true,
|
14579
|
+
numberFilter: true,
|
14580
|
+
orderByFilter: true,
|
14581
|
+
uppercaseFilter: true,
|
14582
|
+
*/
|
14583
|
+
|
14553
14584
|
/**
|
14554
14585
|
* @ngdoc provider
|
14555
14586
|
* @name $filterProvider
|
@@ -14931,14 +14962,15 @@ function filterFilter() {
|
|
14931
14962
|
*
|
14932
14963
|
*
|
14933
14964
|
* @example
|
14934
|
-
<example>
|
14965
|
+
<example module="currencyExample">
|
14935
14966
|
<file name="index.html">
|
14936
14967
|
<script>
|
14937
|
-
|
14938
|
-
$scope
|
14939
|
-
|
14968
|
+
angular.module('currencyExample', [])
|
14969
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
14970
|
+
$scope.amount = 1234.56;
|
14971
|
+
}]);
|
14940
14972
|
</script>
|
14941
|
-
<div ng-controller="
|
14973
|
+
<div ng-controller="ExampleController">
|
14942
14974
|
<input type="number" ng-model="amount"> <br>
|
14943
14975
|
default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br>
|
14944
14976
|
custom currency identifier (USD$): <span>{{amount | currency:"USD$"}}</span>
|
@@ -14990,14 +15022,15 @@ function currencyFilter($locale) {
|
|
14990
15022
|
* @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
|
14991
15023
|
*
|
14992
15024
|
* @example
|
14993
|
-
<example>
|
15025
|
+
<example module="numberFilterExample">
|
14994
15026
|
<file name="index.html">
|
14995
15027
|
<script>
|
14996
|
-
|
14997
|
-
$scope
|
14998
|
-
|
15028
|
+
angular.module('numberFilterExample', [])
|
15029
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
15030
|
+
$scope.val = 1234.56789;
|
15031
|
+
}]);
|
14999
15032
|
</script>
|
15000
|
-
<div ng-controller="
|
15033
|
+
<div ng-controller="ExampleController">
|
15001
15034
|
Enter number: <input ng-model='val'><br>
|
15002
15035
|
Default formatting: <span id='number-default'>{{val | number}}</span><br>
|
15003
15036
|
No fractions: <span>{{val | number:0}}</span><br>
|
@@ -15451,17 +15484,18 @@ var uppercaseFilter = valueFn(uppercase);
|
|
15451
15484
|
* had less than `limit` elements.
|
15452
15485
|
*
|
15453
15486
|
* @example
|
15454
|
-
<example>
|
15487
|
+
<example module="limitToExample">
|
15455
15488
|
<file name="index.html">
|
15456
15489
|
<script>
|
15457
|
-
|
15458
|
-
$scope
|
15459
|
-
|
15460
|
-
|
15461
|
-
|
15462
|
-
|
15490
|
+
angular.module('limitToExample', [])
|
15491
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
15492
|
+
$scope.numbers = [1,2,3,4,5,6,7,8,9];
|
15493
|
+
$scope.letters = "abcdefghi";
|
15494
|
+
$scope.numLimit = 3;
|
15495
|
+
$scope.letterLimit = 3;
|
15496
|
+
}]);
|
15463
15497
|
</script>
|
15464
|
-
<div ng-controller="
|
15498
|
+
<div ng-controller="ExampleController">
|
15465
15499
|
Limit {{numbers}} to: <input type="integer" ng-model="numLimit">
|
15466
15500
|
<p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
|
15467
15501
|
Limit {{letters}} to: <input type="integer" ng-model="letterLimit">
|
@@ -15573,20 +15607,21 @@ function limitToFilter(){
|
|
15573
15607
|
* @returns {Array} Sorted copy of the source array.
|
15574
15608
|
*
|
15575
15609
|
* @example
|
15576
|
-
<example>
|
15610
|
+
<example module="orderByExample">
|
15577
15611
|
<file name="index.html">
|
15578
15612
|
<script>
|
15579
|
-
|
15580
|
-
$scope
|
15581
|
-
|
15582
|
-
|
15583
|
-
|
15584
|
-
|
15585
|
-
|
15586
|
-
|
15587
|
-
|
15613
|
+
angular.module('orderByExample', [])
|
15614
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
15615
|
+
$scope.friends =
|
15616
|
+
[{name:'John', phone:'555-1212', age:10},
|
15617
|
+
{name:'Mary', phone:'555-9876', age:19},
|
15618
|
+
{name:'Mike', phone:'555-4321', age:21},
|
15619
|
+
{name:'Adam', phone:'555-5678', age:35},
|
15620
|
+
{name:'Julie', phone:'555-8765', age:29}];
|
15621
|
+
$scope.predicate = '-age';
|
15622
|
+
}]);
|
15588
15623
|
</script>
|
15589
|
-
<div ng-controller="
|
15624
|
+
<div ng-controller="ExampleController">
|
15590
15625
|
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
|
15591
15626
|
<hr/>
|
15592
15627
|
[ <a href="" ng-click="predicate=''">unsorted</a> ]
|
@@ -15614,7 +15649,7 @@ function limitToFilter(){
|
|
15614
15649
|
* Example:
|
15615
15650
|
*
|
15616
15651
|
* @example
|
15617
|
-
<example>
|
15652
|
+
<example module="orderByExample">
|
15618
15653
|
<file name="index.html">
|
15619
15654
|
<div ng-controller="Ctrl">
|
15620
15655
|
<table class="friend">
|
@@ -15634,21 +15669,21 @@ function limitToFilter(){
|
|
15634
15669
|
</file>
|
15635
15670
|
|
15636
15671
|
<file name="script.js">
|
15637
|
-
|
15638
|
-
|
15639
|
-
|
15640
|
-
|
15641
|
-
|
15642
|
-
|
15643
|
-
|
15644
|
-
|
15645
|
-
|
15646
|
-
|
15647
|
-
|
15648
|
-
|
15649
|
-
|
15650
|
-
|
15651
|
-
|
15672
|
+
angular.module('orderByExample', [])
|
15673
|
+
.controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {
|
15674
|
+
var orderBy = $filter('orderBy');
|
15675
|
+
$scope.friends = [
|
15676
|
+
{ name: 'John', phone: '555-1212', age: 10 },
|
15677
|
+
{ name: 'Mary', phone: '555-9876', age: 19 },
|
15678
|
+
{ name: 'Mike', phone: '555-4321', age: 21 },
|
15679
|
+
{ name: 'Adam', phone: '555-5678', age: 35 },
|
15680
|
+
{ name: 'Julie', phone: '555-8765', age: 29 }
|
15681
|
+
];
|
15682
|
+
$scope.order = function(predicate, reverse) {
|
15683
|
+
$scope.friends = orderBy($scope.friends, predicate, reverse);
|
15684
|
+
};
|
15685
|
+
$scope.order('-age',false);
|
15686
|
+
}]);
|
15652
15687
|
</file>
|
15653
15688
|
</example>
|
15654
15689
|
*/
|
@@ -15834,7 +15869,7 @@ var htmlAnchorDirective = valueFn({
|
|
15834
15869
|
return browser.driver.getCurrentUrl().then(function(url) {
|
15835
15870
|
return url.match(/\/123$/);
|
15836
15871
|
});
|
15837
|
-
},
|
15872
|
+
}, 5000, 'page should navigate to /123');
|
15838
15873
|
});
|
15839
15874
|
|
15840
15875
|
xit('should execute ng-click but not reload when href empty string and name specified', function() {
|
@@ -15862,7 +15897,7 @@ var htmlAnchorDirective = valueFn({
|
|
15862
15897
|
return browser.driver.getCurrentUrl().then(function(url) {
|
15863
15898
|
return url.match(/\/6$/);
|
15864
15899
|
});
|
15865
|
-
},
|
15900
|
+
}, 5000, 'page should navigate to /6');
|
15866
15901
|
});
|
15867
15902
|
</file>
|
15868
15903
|
</example>
|
@@ -16261,6 +16296,23 @@ function FormController(element, attrs, $scope, $animate) {
|
|
16261
16296
|
$animate.addClass(element, (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
|
16262
16297
|
}
|
16263
16298
|
|
16299
|
+
/**
|
16300
|
+
* @ngdoc method
|
16301
|
+
* @name form.FormController#$rollbackViewValue
|
16302
|
+
*
|
16303
|
+
* @description
|
16304
|
+
* Rollback all form controls pending updates to the `$modelValue`.
|
16305
|
+
*
|
16306
|
+
* Updates may be pending by a debounced event or because the input is waiting for a some future
|
16307
|
+
* event defined in `ng-model-options`. This method is typically needed by the reset button of
|
16308
|
+
* a form that uses `ng-model-options` to pend updates.
|
16309
|
+
*/
|
16310
|
+
form.$rollbackViewValue = function() {
|
16311
|
+
forEach(controls, function(control) {
|
16312
|
+
control.$rollbackViewValue();
|
16313
|
+
});
|
16314
|
+
};
|
16315
|
+
|
16264
16316
|
/**
|
16265
16317
|
* @ngdoc method
|
16266
16318
|
* @name form.FormController#$commitViewValue
|
@@ -16522,12 +16574,13 @@ function FormController(element, attrs, $scope, $animate) {
|
|
16522
16574
|
* </pre>
|
16523
16575
|
*
|
16524
16576
|
* @example
|
16525
|
-
<example deps="angular-animate.js" animations="true" fixBase="true">
|
16577
|
+
<example deps="angular-animate.js" animations="true" fixBase="true" module="formExample">
|
16526
16578
|
<file name="index.html">
|
16527
16579
|
<script>
|
16528
|
-
|
16529
|
-
$scope
|
16530
|
-
|
16580
|
+
angular.module('formExample', [])
|
16581
|
+
.controller('FormController', ['$scope', function($scope) {
|
16582
|
+
$scope.userType = 'guest';
|
16583
|
+
}]);
|
16531
16584
|
</script>
|
16532
16585
|
<style>
|
16533
16586
|
.my-form {
|
@@ -16539,7 +16592,7 @@ function FormController(element, attrs, $scope, $animate) {
|
|
16539
16592
|
background: red;
|
16540
16593
|
}
|
16541
16594
|
</style>
|
16542
|
-
<form name="myForm" ng-controller="
|
16595
|
+
<form name="myForm" ng-controller="FormController" class="my-form">
|
16543
16596
|
userType: <input name="input" ng-model="userType" required>
|
16544
16597
|
<span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
|
16545
16598
|
<tt>userType = {{userType}}</tt><br>
|
@@ -16637,18 +16690,16 @@ var formDirectiveFactory = function(isNgForm) {
|
|
16637
16690
|
var formDirective = formDirectiveFactory();
|
16638
16691
|
var ngFormDirective = formDirectiveFactory(true);
|
16639
16692
|
|
16640
|
-
/* global
|
16641
|
-
|
16642
|
-
|
16643
|
-
|
16644
|
-
|
16645
|
-
|
16646
|
-
-UNTOUCHED_CLASS,
|
16647
|
-
-TOUCHED_CLASS
|
16693
|
+
/* global VALID_CLASS: true,
|
16694
|
+
INVALID_CLASS: true,
|
16695
|
+
PRISTINE_CLASS: true,
|
16696
|
+
DIRTY_CLASS: true,
|
16697
|
+
UNTOUCHED_CLASS: true,
|
16698
|
+
TOUCHED_CLASS: true,
|
16648
16699
|
*/
|
16649
16700
|
|
16650
16701
|
var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
|
16651
|
-
var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9-]
|
16702
|
+
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;
|
16652
16703
|
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
|
16653
16704
|
var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
|
16654
16705
|
var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)$/;
|
@@ -16684,15 +16735,16 @@ var inputType = {
|
|
16684
16735
|
* @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
|
16685
16736
|
*
|
16686
16737
|
* @example
|
16687
|
-
<example name="text-input-directive">
|
16738
|
+
<example name="text-input-directive" module="textInputExample">
|
16688
16739
|
<file name="index.html">
|
16689
16740
|
<script>
|
16690
|
-
|
16691
|
-
$scope
|
16692
|
-
|
16693
|
-
|
16741
|
+
angular.module('textInputExample', [])
|
16742
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
16743
|
+
$scope.text = 'guest';
|
16744
|
+
$scope.word = /^\s*\w*\s*$/;
|
16745
|
+
}]);
|
16694
16746
|
</script>
|
16695
|
-
<form name="myForm" ng-controller="
|
16747
|
+
<form name="myForm" ng-controller="ExampleController">
|
16696
16748
|
Single word: <input type="text" name="input" ng-model="text"
|
16697
16749
|
ng-pattern="word" required ng-trim="false">
|
16698
16750
|
<span class="error" ng-show="myForm.input.$error.required">
|
@@ -16759,14 +16811,15 @@ var inputType = {
|
|
16759
16811
|
* interaction with the input element.
|
16760
16812
|
*
|
16761
16813
|
* @example
|
16762
|
-
<example name="date-input-directive">
|
16814
|
+
<example name="date-input-directive" module="dateInputExample">
|
16763
16815
|
<file name="index.html">
|
16764
16816
|
<script>
|
16765
|
-
|
16766
|
-
|
16767
|
-
|
16817
|
+
angular.module('dateInputExample', [])
|
16818
|
+
.controller('DateController', ['$scope', function($scope) {
|
16819
|
+
$scope.value = new Date(2013, 9, 22);
|
16820
|
+
}]);
|
16768
16821
|
</script>
|
16769
|
-
<form name="myForm" ng-controller="
|
16822
|
+
<form name="myForm" ng-controller="DateController as dateCtrl">
|
16770
16823
|
Pick a date between in 2013:
|
16771
16824
|
<input type="date" id="exampleInput" name="input" ng-model="value"
|
16772
16825
|
placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required />
|
@@ -16843,14 +16896,15 @@ var inputType = {
|
|
16843
16896
|
* interaction with the input element.
|
16844
16897
|
*
|
16845
16898
|
* @example
|
16846
|
-
<example name="datetimelocal-input-directive">
|
16899
|
+
<example name="datetimelocal-input-directive" module="dateExample">
|
16847
16900
|
<file name="index.html">
|
16848
16901
|
<script>
|
16849
|
-
|
16850
|
-
|
16851
|
-
|
16902
|
+
angular.module('dateExample', [])
|
16903
|
+
.controller('DateController', ['$scope', function($scope) {
|
16904
|
+
$scope.value = new Date(2010, 11, 28, 14, 57);
|
16905
|
+
}]);
|
16852
16906
|
</script>
|
16853
|
-
<form name="myForm" ng-controller="
|
16907
|
+
<form name="myForm" ng-controller="DateController as dateCtrl">
|
16854
16908
|
Pick a date between in 2013:
|
16855
16909
|
<input type="datetime-local" id="exampleInput" name="input" ng-model="value"
|
16856
16910
|
placeholder="yyyy-MM-ddTHH:mm" min="2001-01-01T00:00" max="2013-12-31T00:00" required />
|
@@ -16928,14 +16982,15 @@ var inputType = {
|
|
16928
16982
|
* interaction with the input element.
|
16929
16983
|
*
|
16930
16984
|
* @example
|
16931
|
-
<example name="time-input-directive">
|
16985
|
+
<example name="time-input-directive" module="timeExample">
|
16932
16986
|
<file name="index.html">
|
16933
16987
|
<script>
|
16934
|
-
|
16935
|
-
|
16936
|
-
|
16988
|
+
angular.module('timeExample', [])
|
16989
|
+
.controller('DateController', ['$scope', function($scope) {
|
16990
|
+
$scope.value = new Date(0, 0, 1, 14, 57);
|
16991
|
+
}]);
|
16937
16992
|
</script>
|
16938
|
-
<form name="myForm" ng-controller="
|
16993
|
+
<form name="myForm" ng-controller="DateController as dateCtrl">
|
16939
16994
|
Pick a between 8am and 5pm:
|
16940
16995
|
<input type="time" id="exampleInput" name="input" ng-model="value"
|
16941
16996
|
placeholder="HH:mm" min="08:00" max="17:00" required />
|
@@ -17012,14 +17067,15 @@ var inputType = {
|
|
17012
17067
|
* interaction with the input element.
|
17013
17068
|
*
|
17014
17069
|
* @example
|
17015
|
-
<example name="week-input-directive">
|
17070
|
+
<example name="week-input-directive" module="weekExample">
|
17016
17071
|
<file name="index.html">
|
17017
17072
|
<script>
|
17018
|
-
|
17019
|
-
|
17020
|
-
|
17073
|
+
angular.module('weekExample', [])
|
17074
|
+
.controller('DateController', ['$scope', function($scope) {
|
17075
|
+
$scope.value = new Date(2013, 0, 3);
|
17076
|
+
}]);
|
17021
17077
|
</script>
|
17022
|
-
<form name="myForm" ng-controller="
|
17078
|
+
<form name="myForm" ng-controller="DateController as dateCtrl">
|
17023
17079
|
Pick a date between in 2013:
|
17024
17080
|
<input id="exampleInput" type="week" name="input" ng-model="value"
|
17025
17081
|
placeholder="YYYY-W##" min="2012-W32" max="2013-W52" required />
|
@@ -17095,14 +17151,15 @@ var inputType = {
|
|
17095
17151
|
* interaction with the input element.
|
17096
17152
|
*
|
17097
17153
|
* @example
|
17098
|
-
<example name="month-input-directive">
|
17154
|
+
<example name="month-input-directive" module="monthExample">
|
17099
17155
|
<file name="index.html">
|
17100
17156
|
<script>
|
17101
|
-
|
17102
|
-
|
17103
|
-
|
17157
|
+
angular.module('monthExample', [])
|
17158
|
+
.controller('DateController', ['$scope', function($scope) {
|
17159
|
+
$scope.value = new Date(2013, 9, 1);
|
17160
|
+
}]);
|
17104
17161
|
</script>
|
17105
|
-
<form name="myForm" ng-controller="
|
17162
|
+
<form name="myForm" ng-controller="DateController as dateCtrl">
|
17106
17163
|
Pick a month int 2013:
|
17107
17164
|
<input id="exampleInput" type="month" name="input" ng-model="value"
|
17108
17165
|
placeholder="yyyy-MM" min="2013-01" max="2013-12" required />
|
@@ -17183,14 +17240,15 @@ var inputType = {
|
|
17183
17240
|
* interaction with the input element.
|
17184
17241
|
*
|
17185
17242
|
* @example
|
17186
|
-
<example name="number-input-directive">
|
17243
|
+
<example name="number-input-directive" module="numberExample">
|
17187
17244
|
<file name="index.html">
|
17188
17245
|
<script>
|
17189
|
-
|
17190
|
-
$scope
|
17191
|
-
|
17246
|
+
angular.module('numberExample', [])
|
17247
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
17248
|
+
$scope.value = 12;
|
17249
|
+
}]);
|
17192
17250
|
</script>
|
17193
|
-
<form name="myForm" ng-controller="
|
17251
|
+
<form name="myForm" ng-controller="ExampleController">
|
17194
17252
|
Number: <input type="number" name="input" ng-model="value"
|
17195
17253
|
min="0" max="99" required>
|
17196
17254
|
<span class="error" ng-show="myForm.input.$error.required">
|
@@ -17258,14 +17316,15 @@ var inputType = {
|
|
17258
17316
|
* interaction with the input element.
|
17259
17317
|
*
|
17260
17318
|
* @example
|
17261
|
-
<example name="url-input-directive">
|
17319
|
+
<example name="url-input-directive" module="urlExample">
|
17262
17320
|
<file name="index.html">
|
17263
17321
|
<script>
|
17264
|
-
|
17265
|
-
$scope
|
17266
|
-
|
17322
|
+
angular.module('urlExample', [])
|
17323
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
17324
|
+
$scope.text = 'http://google.com';
|
17325
|
+
}]);
|
17267
17326
|
</script>
|
17268
|
-
<form name="myForm" ng-controller="
|
17327
|
+
<form name="myForm" ng-controller="ExampleController">
|
17269
17328
|
URL: <input type="url" name="input" ng-model="text" required>
|
17270
17329
|
<span class="error" ng-show="myForm.input.$error.required">
|
17271
17330
|
Required!</span>
|
@@ -17334,14 +17393,15 @@ var inputType = {
|
|
17334
17393
|
* interaction with the input element.
|
17335
17394
|
*
|
17336
17395
|
* @example
|
17337
|
-
<example name="email-input-directive">
|
17396
|
+
<example name="email-input-directive" module="emailExample">
|
17338
17397
|
<file name="index.html">
|
17339
17398
|
<script>
|
17340
|
-
|
17341
|
-
$scope
|
17342
|
-
|
17399
|
+
angular.module('emailExample', [])
|
17400
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
17401
|
+
$scope.text = 'me@example.com';
|
17402
|
+
}]);
|
17343
17403
|
</script>
|
17344
|
-
<form name="myForm" ng-controller="
|
17404
|
+
<form name="myForm" ng-controller="ExampleController">
|
17345
17405
|
Email: <input type="email" name="input" ng-model="text" required>
|
17346
17406
|
<span class="error" ng-show="myForm.input.$error.required">
|
17347
17407
|
Required!</span>
|
@@ -17400,18 +17460,19 @@ var inputType = {
|
|
17400
17460
|
* be set when selected.
|
17401
17461
|
*
|
17402
17462
|
* @example
|
17403
|
-
<example name="radio-input-directive">
|
17463
|
+
<example name="radio-input-directive" module="radioExample">
|
17404
17464
|
<file name="index.html">
|
17405
17465
|
<script>
|
17406
|
-
|
17407
|
-
$scope
|
17408
|
-
|
17409
|
-
|
17410
|
-
|
17411
|
-
|
17412
|
-
|
17466
|
+
angular.module('radioExample', [])
|
17467
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
17468
|
+
$scope.color = 'blue';
|
17469
|
+
$scope.specialValue = {
|
17470
|
+
"id": "12345",
|
17471
|
+
"value": "green"
|
17472
|
+
};
|
17473
|
+
}]);
|
17413
17474
|
</script>
|
17414
|
-
<form name="myForm" ng-controller="
|
17475
|
+
<form name="myForm" ng-controller="ExampleController">
|
17415
17476
|
<input type="radio" ng-model="color" value="red"> Red <br/>
|
17416
17477
|
<input type="radio" ng-model="color" ng-value="specialValue"> Green <br/>
|
17417
17478
|
<input type="radio" ng-model="color" value="blue"> Blue <br/>
|
@@ -17444,24 +17505,25 @@ var inputType = {
|
|
17444
17505
|
*
|
17445
17506
|
* @param {string} ngModel Assignable angular expression to data-bind to.
|
17446
17507
|
* @param {string=} name Property name of the form under which the control is published.
|
17447
|
-
* @param {
|
17448
|
-
* @param {
|
17508
|
+
* @param {expression=} ngTrueValue The value to which the expression should be set when selected.
|
17509
|
+
* @param {expression=} ngFalseValue The value to which the expression should be set when not selected.
|
17449
17510
|
* @param {string=} ngChange Angular expression to be executed when input changes due to user
|
17450
17511
|
* interaction with the input element.
|
17451
17512
|
*
|
17452
17513
|
* @example
|
17453
|
-
<example name="checkbox-input-directive">
|
17514
|
+
<example name="checkbox-input-directive" module="checkboxExample">
|
17454
17515
|
<file name="index.html">
|
17455
17516
|
<script>
|
17456
|
-
|
17457
|
-
$scope
|
17458
|
-
|
17459
|
-
|
17517
|
+
angular.module('checkboxExample', [])
|
17518
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
17519
|
+
$scope.value1 = true;
|
17520
|
+
$scope.value2 = 'YES'
|
17521
|
+
}]);
|
17460
17522
|
</script>
|
17461
|
-
<form name="myForm" ng-controller="
|
17523
|
+
<form name="myForm" ng-controller="ExampleController">
|
17462
17524
|
Value1: <input type="checkbox" ng-model="value1"> <br/>
|
17463
17525
|
Value2: <input type="checkbox" ng-model="value2"
|
17464
|
-
ng-true-value="YES" ng-false-value="NO"> <br/>
|
17526
|
+
ng-true-value="'YES'" ng-false-value="'NO'"> <br/>
|
17465
17527
|
<tt>value1 = {{value1}}</tt><br/>
|
17466
17528
|
<tt>value2 = {{value2}}</tt><br/>
|
17467
17529
|
</form>
|
@@ -17820,12 +17882,22 @@ function radioInputType(scope, element, attr, ctrl) {
|
|
17820
17882
|
attr.$observe('value', ctrl.$render);
|
17821
17883
|
}
|
17822
17884
|
|
17823
|
-
function
|
17824
|
-
var
|
17825
|
-
|
17885
|
+
function parseConstantExpr($parse, context, name, expression, fallback) {
|
17886
|
+
var parseFn;
|
17887
|
+
if (isDefined(expression)) {
|
17888
|
+
parseFn = $parse(expression);
|
17889
|
+
if (!parseFn.constant) {
|
17890
|
+
throw new minErr('ngModel')('constexpr', 'Expected constant expression for `{0}`, but saw ' +
|
17891
|
+
'`{1}`.', name, expression);
|
17892
|
+
}
|
17893
|
+
return parseFn(context);
|
17894
|
+
}
|
17895
|
+
return fallback;
|
17896
|
+
}
|
17826
17897
|
|
17827
|
-
|
17828
|
-
|
17898
|
+
function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {
|
17899
|
+
var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true);
|
17900
|
+
var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);
|
17829
17901
|
|
17830
17902
|
var listener = function(ev) {
|
17831
17903
|
scope.$apply(function() {
|
@@ -17845,7 +17917,7 @@ function checkboxInputType(scope, element, attr, ctrl) {
|
|
17845
17917
|
};
|
17846
17918
|
|
17847
17919
|
ctrl.$formatters.push(function(value) {
|
17848
|
-
return value
|
17920
|
+
return equals(value, trueValue);
|
17849
17921
|
});
|
17850
17922
|
|
17851
17923
|
ctrl.$parsers.push(function(value) {
|
@@ -17907,14 +17979,15 @@ function checkboxInputType(scope, element, attr, ctrl) {
|
|
17907
17979
|
* interaction with the input element.
|
17908
17980
|
*
|
17909
17981
|
* @example
|
17910
|
-
<example name="input-directive">
|
17982
|
+
<example name="input-directive" module="inputExample">
|
17911
17983
|
<file name="index.html">
|
17912
17984
|
<script>
|
17913
|
-
|
17914
|
-
|
17915
|
-
|
17985
|
+
angular.module('inputExample', [])
|
17986
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
17987
|
+
$scope.user = {name: 'guest', last: 'visitor'};
|
17988
|
+
}]);
|
17916
17989
|
</script>
|
17917
|
-
<div ng-controller="
|
17990
|
+
<div ng-controller="ExampleController">
|
17918
17991
|
<form name="myForm">
|
17919
17992
|
User name: <input type="text" name="userName" ng-model="user.name" required>
|
17920
17993
|
<span class="error" ng-show="myForm.userName.$error.required">
|
@@ -17993,14 +18066,15 @@ function checkboxInputType(scope, element, attr, ctrl) {
|
|
17993
18066
|
</file>
|
17994
18067
|
</example>
|
17995
18068
|
*/
|
17996
|
-
var inputDirective = ['$browser', '$sniffer', '$filter',
|
18069
|
+
var inputDirective = ['$browser', '$sniffer', '$filter', '$parse',
|
18070
|
+
function($browser, $sniffer, $filter, $parse) {
|
17997
18071
|
return {
|
17998
18072
|
restrict: 'E',
|
17999
18073
|
require: ['?ngModel'],
|
18000
18074
|
link: function(scope, element, attr, ctrls) {
|
18001
18075
|
if (ctrls[0]) {
|
18002
18076
|
(inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
|
18003
|
-
$browser, $filter);
|
18077
|
+
$browser, $filter, $parse);
|
18004
18078
|
}
|
18005
18079
|
}
|
18006
18080
|
};
|
@@ -18194,6 +18268,18 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
18194
18268
|
* @description
|
18195
18269
|
* Called when the view needs to be updated. It is expected that the user of the ng-model
|
18196
18270
|
* directive will implement this method.
|
18271
|
+
*
|
18272
|
+
* The `$render()` method is invoked in the following situations:
|
18273
|
+
*
|
18274
|
+
* * `$rollbackViewValue()` is called. If we are rolling back the view value to the last
|
18275
|
+
* committed value then `$render()` is called to update the input control.
|
18276
|
+
* * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and
|
18277
|
+
* the `$viewValue` are different to last time.
|
18278
|
+
*
|
18279
|
+
* Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of
|
18280
|
+
* `$modelValue` and `$viewValue` are actually different to their previous value. If `$modelValue`
|
18281
|
+
* or `$viewValue` are objects (rather than a string or number) then `$render()` will not be
|
18282
|
+
* invoked if you only change a property on the objects.
|
18197
18283
|
*/
|
18198
18284
|
this.$render = noop;
|
18199
18285
|
|
@@ -18359,7 +18445,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
18359
18445
|
* <file name="app.js">
|
18360
18446
|
* angular.module('cancel-update-example', [])
|
18361
18447
|
*
|
18362
|
-
* .controller('
|
18448
|
+
* .controller('CancelUpdateController', ['$scope', function($scope) {
|
18363
18449
|
* $scope.resetWithCancel = function (e) {
|
18364
18450
|
* if (e.keyCode == 27) {
|
18365
18451
|
* $scope.myForm.myInput1.$rollbackViewValue();
|
@@ -18371,10 +18457,10 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
18371
18457
|
* $scope.myValue = '';
|
18372
18458
|
* }
|
18373
18459
|
* };
|
18374
|
-
* });
|
18460
|
+
* }]);
|
18375
18461
|
* </file>
|
18376
18462
|
* <file name="index.html">
|
18377
|
-
* <div ng-controller="
|
18463
|
+
* <div ng-controller="CancelUpdateController">
|
18378
18464
|
* <p>Try typing something in each input. See that the model only updates when you
|
18379
18465
|
* blur off the input.
|
18380
18466
|
* </p>
|
@@ -18407,13 +18493,24 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
18407
18493
|
* Runs each of the registered validations set on the $validators object.
|
18408
18494
|
*/
|
18409
18495
|
this.$validate = function() {
|
18410
|
-
|
18496
|
+
// ignore $validate before model initialized
|
18497
|
+
if (ctrl.$modelValue !== ctrl.$modelValue) {
|
18498
|
+
return;
|
18499
|
+
}
|
18500
|
+
|
18501
|
+
var prev = ctrl.$modelValue;
|
18502
|
+
ctrl.$$runValidators(ctrl.$$invalidModelValue || ctrl.$modelValue, ctrl.$viewValue);
|
18503
|
+
if (prev !== ctrl.$modelValue) {
|
18504
|
+
ctrl.$$writeModelToScope();
|
18505
|
+
}
|
18411
18506
|
};
|
18412
18507
|
|
18413
18508
|
this.$$runValidators = function(modelValue, viewValue) {
|
18414
18509
|
forEach(ctrl.$validators, function(fn, name) {
|
18415
18510
|
ctrl.$setValidity(name, fn(modelValue, viewValue));
|
18416
18511
|
});
|
18512
|
+
ctrl.$modelValue = ctrl.$valid ? modelValue : undefined;
|
18513
|
+
ctrl.$$invalidModelValue = ctrl.$valid ? undefined : modelValue;
|
18417
18514
|
};
|
18418
18515
|
|
18419
18516
|
/**
|
@@ -18452,20 +18549,28 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
18452
18549
|
|
18453
18550
|
if (ctrl.$modelValue !== modelValue &&
|
18454
18551
|
(isUndefined(ctrl.$$invalidModelValue) || ctrl.$$invalidModelValue != modelValue)) {
|
18455
|
-
|
18456
18552
|
ctrl.$$runValidators(modelValue, viewValue);
|
18457
|
-
ctrl
|
18458
|
-
|
18553
|
+
ctrl.$$writeModelToScope();
|
18554
|
+
}
|
18555
|
+
};
|
18556
|
+
|
18557
|
+
this.$$writeModelToScope = function() {
|
18558
|
+
var getterSetter;
|
18559
|
+
|
18560
|
+
if (ctrl.$options && ctrl.$options.getterSetter &&
|
18561
|
+
isFunction(getterSetter = ngModelGet($scope))) {
|
18459
18562
|
|
18563
|
+
getterSetter(ctrl.$modelValue);
|
18564
|
+
} else {
|
18460
18565
|
ngModelSet($scope, ctrl.$modelValue);
|
18461
|
-
forEach(ctrl.$viewChangeListeners, function(listener) {
|
18462
|
-
try {
|
18463
|
-
listener();
|
18464
|
-
} catch(e) {
|
18465
|
-
$exceptionHandler(e);
|
18466
|
-
}
|
18467
|
-
});
|
18468
18566
|
}
|
18567
|
+
forEach(ctrl.$viewChangeListeners, function(listener) {
|
18568
|
+
try {
|
18569
|
+
listener();
|
18570
|
+
} catch(e) {
|
18571
|
+
$exceptionHandler(e);
|
18572
|
+
}
|
18573
|
+
});
|
18469
18574
|
};
|
18470
18575
|
|
18471
18576
|
/**
|
@@ -18475,13 +18580,25 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
18475
18580
|
* @description
|
18476
18581
|
* Update the view value.
|
18477
18582
|
*
|
18478
|
-
* This method should be called when
|
18479
|
-
*
|
18480
|
-
*
|
18583
|
+
* This method should be called when an input directive want to change the view value; typically,
|
18584
|
+
* this is done from within a DOM event handler.
|
18585
|
+
*
|
18586
|
+
* For example {@link ng.directive:input input} calls it when the value of the input changes and
|
18587
|
+
* {@link ng.directive:select select} calls it when an option is selected.
|
18481
18588
|
*
|
18482
|
-
*
|
18483
|
-
*
|
18484
|
-
*
|
18589
|
+
* If the new `value` is an object (rather than a string or a number), we should make a copy of the
|
18590
|
+
* object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep
|
18591
|
+
* watch of objects, it only looks for a change of identity. If you only change the property of
|
18592
|
+
* the object then ngModel will not realise that the object has changed and will not invoke the
|
18593
|
+
* `$parsers` and `$validators` pipelines.
|
18594
|
+
*
|
18595
|
+
* For this reason, you should not change properties of the copy once it has been passed to
|
18596
|
+
* `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly.
|
18597
|
+
*
|
18598
|
+
* When this method is called, the new `value` will be staged for committing through the `$parsers`
|
18599
|
+
* and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged
|
18600
|
+
* value sent directly for processing, finally to be applied to `$modelValue` and then the
|
18601
|
+
* **expression** specified in the `ng-model` attribute.
|
18485
18602
|
*
|
18486
18603
|
* Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
|
18487
18604
|
*
|
@@ -18533,6 +18650,10 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
18533
18650
|
$scope.$watch(function ngModelWatch() {
|
18534
18651
|
var modelValue = ngModelGet($scope);
|
18535
18652
|
|
18653
|
+
if (ctrl.$options && ctrl.$options.getterSetter && isFunction(modelValue)) {
|
18654
|
+
modelValue = modelValue();
|
18655
|
+
}
|
18656
|
+
|
18536
18657
|
// if scope model value and ngModel value are out of sync
|
18537
18658
|
if (ctrl.$modelValue !== modelValue &&
|
18538
18659
|
(isUndefined(ctrl.$$invalidModelValue) || ctrl.$$invalidModelValue != modelValue)) {
|
@@ -18546,8 +18667,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
18546
18667
|
}
|
18547
18668
|
|
18548
18669
|
ctrl.$$runValidators(modelValue, viewValue);
|
18549
|
-
ctrl.$modelValue = ctrl.$valid ? modelValue : undefined;
|
18550
|
-
ctrl.$$invalidModelValue = ctrl.$valid ? undefined : modelValue;
|
18551
18670
|
|
18552
18671
|
if (ctrl.$viewValue !== viewValue) {
|
18553
18672
|
ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
|
@@ -18641,12 +18760,13 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
18641
18760
|
* </pre>
|
18642
18761
|
*
|
18643
18762
|
* @example
|
18644
|
-
* <example deps="angular-animate.js" animations="true" fixBase="true">
|
18763
|
+
* <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample">
|
18645
18764
|
<file name="index.html">
|
18646
18765
|
<script>
|
18647
|
-
|
18648
|
-
$scope
|
18649
|
-
|
18766
|
+
angular.module('inputExample', [])
|
18767
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
18768
|
+
$scope.val = '1';
|
18769
|
+
}]);
|
18650
18770
|
</script>
|
18651
18771
|
<style>
|
18652
18772
|
.my-input {
|
@@ -18661,11 +18781,60 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
18661
18781
|
</style>
|
18662
18782
|
Update input to see transitions when valid/invalid.
|
18663
18783
|
Integer is a valid value.
|
18664
|
-
<form name="testForm" ng-controller="
|
18784
|
+
<form name="testForm" ng-controller="ExampleController">
|
18665
18785
|
<input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input" />
|
18666
18786
|
</form>
|
18667
18787
|
</file>
|
18668
18788
|
* </example>
|
18789
|
+
*
|
18790
|
+
* ## Binding to a getter/setter
|
18791
|
+
*
|
18792
|
+
* Sometimes it's helpful to bind `ngModel` to a getter/setter function. A getter/setter is a
|
18793
|
+
* function that returns a representation of the model when called with zero arguments, and sets
|
18794
|
+
* the internal state of a model when called with an argument. It's sometimes useful to use this
|
18795
|
+
* for models that have an internal representation that's different than what the model exposes
|
18796
|
+
* to the view.
|
18797
|
+
*
|
18798
|
+
* <div class="alert alert-success">
|
18799
|
+
* **Best Practice:** It's best to keep getters fast because Angular is likely to call them more
|
18800
|
+
* frequently than other parts of your code.
|
18801
|
+
* </div>
|
18802
|
+
*
|
18803
|
+
* You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that
|
18804
|
+
* has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to
|
18805
|
+
* a `<form>`, which will enable this behavior for all `<input>`s within it. See
|
18806
|
+
* {@link ng.directive:ngModelOptions `ngModelOptions`} for more.
|
18807
|
+
*
|
18808
|
+
* The following example shows how to use `ngModel` with a getter/setter:
|
18809
|
+
*
|
18810
|
+
* @example
|
18811
|
+
* <example name="ngModel-getter-setter" module="getterSetterExample">
|
18812
|
+
<file name="index.html">
|
18813
|
+
<div ng-controller="ExampleController">
|
18814
|
+
<form name="userForm">
|
18815
|
+
Name:
|
18816
|
+
<input type="text" name="userName"
|
18817
|
+
ng-model="user.name"
|
18818
|
+
ng-model-options="{ getterSetter: true }" />
|
18819
|
+
</form>
|
18820
|
+
<pre>user.name = <span ng-bind="user.name()"></span></pre>
|
18821
|
+
</div>
|
18822
|
+
</file>
|
18823
|
+
<file name="app.js">
|
18824
|
+
angular.module('getterSetterExample', [])
|
18825
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
18826
|
+
var _name = 'Brian';
|
18827
|
+
$scope.user = {
|
18828
|
+
name: function (newName) {
|
18829
|
+
if (angular.isDefined(newName)) {
|
18830
|
+
_name = newName;
|
18831
|
+
}
|
18832
|
+
return _name;
|
18833
|
+
}
|
18834
|
+
};
|
18835
|
+
}]);
|
18836
|
+
</file>
|
18837
|
+
* </example>
|
18669
18838
|
*/
|
18670
18839
|
var ngModelDirective = function() {
|
18671
18840
|
return {
|
@@ -18728,17 +18897,18 @@ var ngModelDirective = function() {
|
|
18728
18897
|
* in input value.
|
18729
18898
|
*
|
18730
18899
|
* @example
|
18731
|
-
* <example name="ngChange-directive">
|
18900
|
+
* <example name="ngChange-directive" module="changeExample">
|
18732
18901
|
* <file name="index.html">
|
18733
18902
|
* <script>
|
18734
|
-
*
|
18735
|
-
* $scope
|
18736
|
-
*
|
18737
|
-
* $scope.
|
18738
|
-
*
|
18739
|
-
*
|
18903
|
+
* angular.module('changeExample', [])
|
18904
|
+
* .controller('ExampleController', ['$scope', function($scope) {
|
18905
|
+
* $scope.counter = 0;
|
18906
|
+
* $scope.change = function() {
|
18907
|
+
* $scope.counter++;
|
18908
|
+
* };
|
18909
|
+
* }]);
|
18740
18910
|
* </script>
|
18741
|
-
* <div ng-controller="
|
18911
|
+
* <div ng-controller="ExampleController">
|
18742
18912
|
* <input type="checkbox" ng-model="confirmed" ng-change="change()" id="ng-change-example1" />
|
18743
18913
|
* <input type="checkbox" ng-model="confirmed" id="ng-change-example2" />
|
18744
18914
|
* <label for="ng-change-example2">Confirmed</label><br />
|
@@ -18877,14 +19047,15 @@ var minlengthDirective = function() {
|
|
18877
19047
|
* specified in form `/something/` then the value will be converted into a regular expression.
|
18878
19048
|
*
|
18879
19049
|
* @example
|
18880
|
-
<example name="ngList-directive">
|
19050
|
+
<example name="ngList-directive" module="listExample">
|
18881
19051
|
<file name="index.html">
|
18882
19052
|
<script>
|
18883
|
-
|
18884
|
-
|
18885
|
-
|
19053
|
+
angular.module('listExample', [])
|
19054
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
19055
|
+
$scope.names = ['igor', 'misko', 'vojta'];
|
19056
|
+
}]);
|
18886
19057
|
</script>
|
18887
|
-
<form name="myForm" ng-controller="
|
19058
|
+
<form name="myForm" ng-controller="ExampleController">
|
18888
19059
|
List: <input name="namesInput" ng-model="names" ng-list required>
|
18889
19060
|
<span class="error" ng-show="myForm.namesInput.$error.required">
|
18890
19061
|
Required!</span>
|
@@ -18976,15 +19147,16 @@ var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
|
|
18976
19147
|
* of the `input` element
|
18977
19148
|
*
|
18978
19149
|
* @example
|
18979
|
-
<example name="ngValue-directive">
|
19150
|
+
<example name="ngValue-directive" module="valueExample">
|
18980
19151
|
<file name="index.html">
|
18981
19152
|
<script>
|
18982
|
-
|
18983
|
-
|
18984
|
-
|
18985
|
-
|
19153
|
+
angular.module('valueExample', [])
|
19154
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
19155
|
+
$scope.names = ['pizza', 'unicorns', 'robots'];
|
19156
|
+
$scope.my = { favorite: 'unicorns' };
|
19157
|
+
}]);
|
18986
19158
|
</script>
|
18987
|
-
<form ng-controller="
|
19159
|
+
<form ng-controller="ExampleController">
|
18988
19160
|
<h2>Which is your favorite?</h2>
|
18989
19161
|
<label ng-repeat="name in names" for="{{name}}">
|
18990
19162
|
{{name}}
|
@@ -19060,6 +19232,8 @@ var ngValueDirective = function() {
|
|
19060
19232
|
* value of 0 triggers an immediate update. If an object is supplied instead, you can specify a
|
19061
19233
|
* custom value for each event. For example:
|
19062
19234
|
* `ngModelOptions="{ updateOn: 'default blur', debounce: {'default': 500, 'blur': 0} }"`
|
19235
|
+
* - `getterSetter`: boolean value which determines whether or not to treat functions bound to
|
19236
|
+
`ngModel` as getters/setters.
|
19063
19237
|
*
|
19064
19238
|
* @example
|
19065
19239
|
|
@@ -19067,9 +19241,9 @@ var ngValueDirective = function() {
|
|
19067
19241
|
form will update the model only when the control loses focus (blur event). If `escape` key is
|
19068
19242
|
pressed while the input field is focused, the value is reset to the value in the current model.
|
19069
19243
|
|
19070
|
-
<example name="ngModelOptions-directive-blur">
|
19244
|
+
<example name="ngModelOptions-directive-blur" module="optionsExample">
|
19071
19245
|
<file name="index.html">
|
19072
|
-
<div ng-controller="
|
19246
|
+
<div ng-controller="ExampleController">
|
19073
19247
|
<form name="userForm">
|
19074
19248
|
Name:
|
19075
19249
|
<input type="text" name="userName"
|
@@ -19084,15 +19258,16 @@ var ngValueDirective = function() {
|
|
19084
19258
|
</div>
|
19085
19259
|
</file>
|
19086
19260
|
<file name="app.js">
|
19087
|
-
|
19088
|
-
|
19261
|
+
angular.module('optionsExample', [])
|
19262
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
19263
|
+
$scope.user = { name: 'say', data: '' };
|
19089
19264
|
|
19090
|
-
|
19091
|
-
|
19092
|
-
|
19093
|
-
|
19094
|
-
|
19095
|
-
|
19265
|
+
$scope.cancel = function (e) {
|
19266
|
+
if (e.keyCode == 27) {
|
19267
|
+
$scope.userForm.userName.$rollbackViewValue();
|
19268
|
+
}
|
19269
|
+
};
|
19270
|
+
}]);
|
19096
19271
|
</file>
|
19097
19272
|
<file name="protractor.js" type="protractor">
|
19098
19273
|
var model = element(by.binding('user.name'));
|
@@ -19121,9 +19296,9 @@ var ngValueDirective = function() {
|
|
19121
19296
|
This one shows how to debounce model changes. Model will be updated only 1 sec after last change.
|
19122
19297
|
If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty.
|
19123
19298
|
|
19124
|
-
<example name="ngModelOptions-directive-debounce">
|
19299
|
+
<example name="ngModelOptions-directive-debounce" module="optionsExample">
|
19125
19300
|
<file name="index.html">
|
19126
|
-
<div ng-controller="
|
19301
|
+
<div ng-controller="ExampleController">
|
19127
19302
|
<form name="userForm">
|
19128
19303
|
Name:
|
19129
19304
|
<input type="text" name="userName"
|
@@ -19135,9 +19310,37 @@ var ngValueDirective = function() {
|
|
19135
19310
|
</div>
|
19136
19311
|
</file>
|
19137
19312
|
<file name="app.js">
|
19138
|
-
|
19139
|
-
$scope
|
19140
|
-
|
19313
|
+
angular.module('optionsExample', [])
|
19314
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
19315
|
+
$scope.user = { name: 'say' };
|
19316
|
+
}]);
|
19317
|
+
</file>
|
19318
|
+
</example>
|
19319
|
+
|
19320
|
+
This one shows how to bind to getter/setters:
|
19321
|
+
|
19322
|
+
<example name="ngModelOptions-directive-getter-setter" module="getterSetterExample">
|
19323
|
+
<file name="index.html">
|
19324
|
+
<div ng-controller="ExampleController">
|
19325
|
+
<form name="userForm">
|
19326
|
+
Name:
|
19327
|
+
<input type="text" name="userName"
|
19328
|
+
ng-model="user.name"
|
19329
|
+
ng-model-options="{ getterSetter: true }" />
|
19330
|
+
</form>
|
19331
|
+
<pre>user.name = <span ng-bind="user.name()"></span></pre>
|
19332
|
+
</div>
|
19333
|
+
</file>
|
19334
|
+
<file name="app.js">
|
19335
|
+
angular.module('getterSetterExample', [])
|
19336
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
19337
|
+
var _name = 'Brian';
|
19338
|
+
$scope.user = {
|
19339
|
+
name: function (newName) {
|
19340
|
+
return angular.isDefined(newName) ? (_name = newName) : _name;
|
19341
|
+
}
|
19342
|
+
};
|
19343
|
+
}]);
|
19141
19344
|
</file>
|
19142
19345
|
</example>
|
19143
19346
|
*/
|
@@ -19187,14 +19390,15 @@ var ngModelOptionsDirective = function() {
|
|
19187
19390
|
*
|
19188
19391
|
* @example
|
19189
19392
|
* Enter a name in the Live Preview text box; the greeting below the text box changes instantly.
|
19190
|
-
<example>
|
19393
|
+
<example module="bindExample">
|
19191
19394
|
<file name="index.html">
|
19192
19395
|
<script>
|
19193
|
-
|
19194
|
-
$scope
|
19195
|
-
|
19396
|
+
angular.module('bindExample', [])
|
19397
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
19398
|
+
$scope.name = 'Whirled';
|
19399
|
+
}]);
|
19196
19400
|
</script>
|
19197
|
-
<div ng-controller="
|
19401
|
+
<div ng-controller="ExampleController">
|
19198
19402
|
Enter name: <input type="text" ng-model="name"><br>
|
19199
19403
|
Hello <span ng-bind="name"></span>!
|
19200
19404
|
</div>
|
@@ -19245,15 +19449,16 @@ var ngBindDirective = ngDirective({
|
|
19245
19449
|
*
|
19246
19450
|
* @example
|
19247
19451
|
* Try it here: enter text in text box and watch the greeting change.
|
19248
|
-
<example>
|
19452
|
+
<example module="bindExample">
|
19249
19453
|
<file name="index.html">
|
19250
19454
|
<script>
|
19251
|
-
|
19252
|
-
$scope
|
19253
|
-
|
19254
|
-
|
19455
|
+
angular.module('bindExample', [])
|
19456
|
+
.controller('ExampleController', ['$scope', function ($scope) {
|
19457
|
+
$scope.salutation = 'Hello';
|
19458
|
+
$scope.name = 'World';
|
19459
|
+
}]);
|
19255
19460
|
</script>
|
19256
|
-
<div ng-controller="
|
19461
|
+
<div ng-controller="ExampleController">
|
19257
19462
|
Salutation: <input type="text" ng-model="salutation"><br>
|
19258
19463
|
Name: <input type="text" ng-model="name"><br>
|
19259
19464
|
<pre ng-bind-template="{{salutation}} {{name}}!"></pre>
|
@@ -19311,20 +19516,20 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
|
|
19311
19516
|
* @example
|
19312
19517
|
Try it here: enter text in text box and watch the greeting change.
|
19313
19518
|
|
19314
|
-
<example module="
|
19519
|
+
<example module="bindHtmlExample" deps="angular-sanitize.js">
|
19315
19520
|
<file name="index.html">
|
19316
|
-
<div ng-controller="
|
19521
|
+
<div ng-controller="ExampleController">
|
19317
19522
|
<p ng-bind-html="myHTML"></p>
|
19318
19523
|
</div>
|
19319
19524
|
</file>
|
19320
19525
|
|
19321
19526
|
<file name="script.js">
|
19322
|
-
angular.module('
|
19323
|
-
|
19324
|
-
|
19325
|
-
|
19326
|
-
|
19327
|
-
|
19527
|
+
angular.module('bindHtmlExample', ['ngSanitize'])
|
19528
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
19529
|
+
$scope.myHTML =
|
19530
|
+
'I am an <code>HTML</code>string with ' +
|
19531
|
+
'<a href="#">links!</a> and other <em>stuff</em>';
|
19532
|
+
}]);
|
19328
19533
|
</file>
|
19329
19534
|
|
19330
19535
|
<file name="protractor.js" type="protractor">
|
@@ -19827,7 +20032,7 @@ var ngCloakDirective = ngDirective({
|
|
19827
20032
|
*
|
19828
20033
|
* This example demonstrates the `controller as` syntax.
|
19829
20034
|
*
|
19830
|
-
* <example name="ngControllerAs">
|
20035
|
+
* <example name="ngControllerAs" module="controllerAsExample">
|
19831
20036
|
* <file name="index.html">
|
19832
20037
|
* <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
|
19833
20038
|
* Name: <input type="text" ng-model="settings.name"/>
|
@@ -19848,6 +20053,9 @@ var ngCloakDirective = ngDirective({
|
|
19848
20053
|
* </div>
|
19849
20054
|
* </file>
|
19850
20055
|
* <file name="app.js">
|
20056
|
+
* angular.module('controllerAsExample', [])
|
20057
|
+
* .controller('SettingsController1', SettingsController1);
|
20058
|
+
*
|
19851
20059
|
* function SettingsController1() {
|
19852
20060
|
* this.name = "John Smith";
|
19853
20061
|
* this.contacts = [
|
@@ -19876,29 +20084,29 @@ var ngCloakDirective = ngDirective({
|
|
19876
20084
|
* <file name="protractor.js" type="protractor">
|
19877
20085
|
* it('should check controller as', function() {
|
19878
20086
|
* var container = element(by.id('ctrl-as-exmpl'));
|
19879
|
-
* expect(container.
|
20087
|
+
* expect(container.element(by.model('settings.name'))
|
19880
20088
|
* .getAttribute('value')).toBe('John Smith');
|
19881
20089
|
*
|
19882
20090
|
* var firstRepeat =
|
19883
|
-
* container.
|
20091
|
+
* container.element(by.repeater('contact in settings.contacts').row(0));
|
19884
20092
|
* var secondRepeat =
|
19885
|
-
* container.
|
20093
|
+
* container.element(by.repeater('contact in settings.contacts').row(1));
|
19886
20094
|
*
|
19887
|
-
* expect(firstRepeat.
|
20095
|
+
* expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
|
19888
20096
|
* .toBe('408 555 1212');
|
19889
20097
|
*
|
19890
|
-
* expect(secondRepeat.
|
20098
|
+
* expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
|
19891
20099
|
* .toBe('john.smith@example.org');
|
19892
20100
|
*
|
19893
|
-
* firstRepeat.
|
20101
|
+
* firstRepeat.element(by.linkText('clear')).click();
|
19894
20102
|
*
|
19895
|
-
* expect(firstRepeat.
|
20103
|
+
* expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
|
19896
20104
|
* .toBe('');
|
19897
20105
|
*
|
19898
|
-
* container.
|
20106
|
+
* container.element(by.linkText('add')).click();
|
19899
20107
|
*
|
19900
|
-
* expect(container.
|
19901
|
-
* .
|
20108
|
+
* expect(container.element(by.repeater('contact in settings.contacts').row(2))
|
20109
|
+
* .element(by.model('contact.value'))
|
19902
20110
|
* .getAttribute('value'))
|
19903
20111
|
* .toBe('yourname@example.org');
|
19904
20112
|
* });
|
@@ -19907,7 +20115,7 @@ var ngCloakDirective = ngDirective({
|
|
19907
20115
|
*
|
19908
20116
|
* This example demonstrates the "attach to `$scope`" style of controller.
|
19909
20117
|
*
|
19910
|
-
* <example name="ngController">
|
20118
|
+
* <example name="ngController" module="controllerExample">
|
19911
20119
|
* <file name="index.html">
|
19912
20120
|
* <div id="ctrl-exmpl" ng-controller="SettingsController2">
|
19913
20121
|
* Name: <input type="text" ng-model="name"/>
|
@@ -19928,6 +20136,9 @@ var ngCloakDirective = ngDirective({
|
|
19928
20136
|
* </div>
|
19929
20137
|
* </file>
|
19930
20138
|
* <file name="app.js">
|
20139
|
+
* angular.module('controllerExample', [])
|
20140
|
+
* .controller('SettingsController2', ['$scope', SettingsController2]);
|
20141
|
+
*
|
19931
20142
|
* function SettingsController2($scope) {
|
19932
20143
|
* $scope.name = "John Smith";
|
19933
20144
|
* $scope.contacts = [
|
@@ -19957,28 +20168,28 @@ var ngCloakDirective = ngDirective({
|
|
19957
20168
|
* it('should check controller', function() {
|
19958
20169
|
* var container = element(by.id('ctrl-exmpl'));
|
19959
20170
|
*
|
19960
|
-
* expect(container.
|
20171
|
+
* expect(container.element(by.model('name'))
|
19961
20172
|
* .getAttribute('value')).toBe('John Smith');
|
19962
20173
|
*
|
19963
20174
|
* var firstRepeat =
|
19964
|
-
* container.
|
20175
|
+
* container.element(by.repeater('contact in contacts').row(0));
|
19965
20176
|
* var secondRepeat =
|
19966
|
-
* container.
|
20177
|
+
* container.element(by.repeater('contact in contacts').row(1));
|
19967
20178
|
*
|
19968
|
-
* expect(firstRepeat.
|
20179
|
+
* expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
|
19969
20180
|
* .toBe('408 555 1212');
|
19970
|
-
* expect(secondRepeat.
|
20181
|
+
* expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
|
19971
20182
|
* .toBe('john.smith@example.org');
|
19972
20183
|
*
|
19973
|
-
* firstRepeat.
|
20184
|
+
* firstRepeat.element(by.linkText('clear')).click();
|
19974
20185
|
*
|
19975
|
-
* expect(firstRepeat.
|
20186
|
+
* expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
|
19976
20187
|
* .toBe('');
|
19977
20188
|
*
|
19978
|
-
* container.
|
20189
|
+
* container.element(by.linkText('add')).click();
|
19979
20190
|
*
|
19980
|
-
* expect(container.
|
19981
|
-
* .
|
20191
|
+
* expect(container.element(by.repeater('contact in contacts').row(2))
|
20192
|
+
* .element(by.model('contact.value'))
|
19982
20193
|
* .getAttribute('value'))
|
19983
20194
|
* .toBe('yourname@example.org');
|
19984
20195
|
* });
|
@@ -20349,21 +20560,22 @@ forEach(
|
|
20349
20560
|
* ({@link guide/expression#-event- Event object is available as `$event`})
|
20350
20561
|
*
|
20351
20562
|
* @example
|
20352
|
-
<example>
|
20563
|
+
<example module="submitExample">
|
20353
20564
|
<file name="index.html">
|
20354
20565
|
<script>
|
20355
|
-
|
20356
|
-
$scope
|
20357
|
-
|
20358
|
-
|
20359
|
-
|
20360
|
-
$scope.
|
20361
|
-
|
20362
|
-
|
20363
|
-
|
20364
|
-
|
20566
|
+
angular.module('submitExample', [])
|
20567
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
20568
|
+
$scope.list = [];
|
20569
|
+
$scope.text = 'hello';
|
20570
|
+
$scope.submit = function() {
|
20571
|
+
if ($scope.text) {
|
20572
|
+
$scope.list.push(this.text);
|
20573
|
+
$scope.text = '';
|
20574
|
+
}
|
20575
|
+
};
|
20576
|
+
}]);
|
20365
20577
|
</script>
|
20366
|
-
<form ng-submit="submit()" ng-controller="
|
20578
|
+
<form ng-submit="submit()" ng-controller="ExampleController">
|
20367
20579
|
Enter text and hit enter:
|
20368
20580
|
<input type="text" ng-model="text" name="text" />
|
20369
20581
|
<input type="submit" id="submit" value="Submit" />
|
@@ -20375,7 +20587,7 @@ forEach(
|
|
20375
20587
|
expect(element(by.binding('list')).getText()).toBe('list=[]');
|
20376
20588
|
element(by.css('#submit')).click();
|
20377
20589
|
expect(element(by.binding('list')).getText()).toContain('hello');
|
20378
|
-
expect(element(by.
|
20590
|
+
expect(element(by.model('text')).getAttribute('value')).toBe('');
|
20379
20591
|
});
|
20380
20592
|
it('should ignore empty strings', function() {
|
20381
20593
|
expect(element(by.binding('list')).getText()).toBe('list=[]');
|
@@ -20648,9 +20860,9 @@ var ngIfDirective = ['$animate', function($animate) {
|
|
20648
20860
|
* - Otherwise enable scrolling only if the expression evaluates to truthy value.
|
20649
20861
|
*
|
20650
20862
|
* @example
|
20651
|
-
<example module="
|
20863
|
+
<example module="includeExample" deps="angular-animate.js" animations="true">
|
20652
20864
|
<file name="index.html">
|
20653
|
-
<div ng-controller="
|
20865
|
+
<div ng-controller="ExampleController">
|
20654
20866
|
<select ng-model="template" ng-options="t.name for t in templates">
|
20655
20867
|
<option value="">(blank)</option>
|
20656
20868
|
</select>
|
@@ -20662,12 +20874,13 @@ var ngIfDirective = ['$animate', function($animate) {
|
|
20662
20874
|
</div>
|
20663
20875
|
</file>
|
20664
20876
|
<file name="script.js">
|
20665
|
-
|
20666
|
-
$scope
|
20667
|
-
|
20668
|
-
{ name: '
|
20669
|
-
|
20670
|
-
|
20877
|
+
angular.module('includeExample', ['ngAnimate'])
|
20878
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
20879
|
+
$scope.templates =
|
20880
|
+
[ { name: 'template1.html', url: 'template1.html'},
|
20881
|
+
{ name: 'template2.html', url: 'template2.html'} ];
|
20882
|
+
$scope.template = $scope.templates[0];
|
20883
|
+
}]);
|
20671
20884
|
</file>
|
20672
20885
|
<file name="template1.html">
|
20673
20886
|
Content of template1.html
|
@@ -20730,7 +20943,7 @@ var ngIfDirective = ['$animate', function($animate) {
|
|
20730
20943
|
return;
|
20731
20944
|
}
|
20732
20945
|
templateSelect.click();
|
20733
|
-
templateSelect.
|
20946
|
+
templateSelect.all(by.css('option')).get(2).click();
|
20734
20947
|
expect(includeElem.getText()).toMatch(/Content of template2.html/);
|
20735
20948
|
});
|
20736
20949
|
|
@@ -20740,7 +20953,7 @@ var ngIfDirective = ['$animate', function($animate) {
|
|
20740
20953
|
return;
|
20741
20954
|
}
|
20742
20955
|
templateSelect.click();
|
20743
|
-
templateSelect.
|
20956
|
+
templateSelect.all(by.css('option')).get(0).click();
|
20744
20957
|
expect(includeElem.isPresent()).toBe(false);
|
20745
20958
|
});
|
20746
20959
|
</file>
|
@@ -20768,8 +20981,7 @@ var ngIfDirective = ['$animate', function($animate) {
|
|
20768
20981
|
|
20769
20982
|
/**
|
20770
20983
|
* @ngdoc event
|
20771
|
-
* @name
|
20772
|
-
* @eventOf ng.directive:ngInclude
|
20984
|
+
* @name ngInclude#$includeContentError
|
20773
20985
|
* @eventType emit on the scope ngInclude was declared in
|
20774
20986
|
* @description
|
20775
20987
|
* Emitted when a template HTTP request yields an erronous response (status < 200 || status > 299)
|
@@ -20905,14 +21117,15 @@ var ngIncludeFillContentDirective = ['$compile',
|
|
20905
21117
|
* @param {expression} ngInit {@link guide/expression Expression} to eval.
|
20906
21118
|
*
|
20907
21119
|
* @example
|
20908
|
-
<example>
|
21120
|
+
<example module="initExample">
|
20909
21121
|
<file name="index.html">
|
20910
21122
|
<script>
|
20911
|
-
|
20912
|
-
|
20913
|
-
|
21123
|
+
angular.module('initExample', [])
|
21124
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
21125
|
+
$scope.list = [['a', 'b'], ['c', 'd']];
|
21126
|
+
}]);
|
20914
21127
|
</script>
|
20915
|
-
<div ng-controller="
|
21128
|
+
<div ng-controller="ExampleController">
|
20916
21129
|
<div ng-repeat="innerList in list" ng-init="outerIndex = $index">
|
20917
21130
|
<div ng-repeat="value in innerList" ng-init="innerIndex = $index">
|
20918
21131
|
<span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>
|
@@ -21065,16 +21278,17 @@ var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });
|
|
21065
21278
|
* @param {number=} offset Offset to deduct from the total number.
|
21066
21279
|
*
|
21067
21280
|
* @example
|
21068
|
-
<example>
|
21281
|
+
<example module="pluralizeExample">
|
21069
21282
|
<file name="index.html">
|
21070
21283
|
<script>
|
21071
|
-
|
21072
|
-
$scope
|
21073
|
-
|
21074
|
-
|
21075
|
-
|
21284
|
+
angular.module('pluralizeExample', [])
|
21285
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
21286
|
+
$scope.person1 = 'Igor';
|
21287
|
+
$scope.person2 = 'Misko';
|
21288
|
+
$scope.personCount = 1;
|
21289
|
+
}]);
|
21076
21290
|
</script>
|
21077
|
-
<div ng-controller="
|
21291
|
+
<div ng-controller="ExampleController">
|
21078
21292
|
Person 1:<input type="text" ng-model="person1" value="Igor" /><br/>
|
21079
21293
|
Person 2:<input type="text" ng-model="person2" value="Misko" /><br/>
|
21080
21294
|
Number of People:<input type="text" ng-model="personCount" value="1" /><br/>
|
@@ -22006,9 +22220,9 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
|
|
22006
22220
|
*
|
22007
22221
|
*
|
22008
22222
|
* @example
|
22009
|
-
<example module="
|
22223
|
+
<example module="switchExample" deps="angular-animate.js" animations="true">
|
22010
22224
|
<file name="index.html">
|
22011
|
-
<div ng-controller="
|
22225
|
+
<div ng-controller="ExampleController">
|
22012
22226
|
<select ng-model="selection" ng-options="item for item in items">
|
22013
22227
|
</select>
|
22014
22228
|
<tt>selection={{selection}}</tt>
|
@@ -22022,10 +22236,11 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
|
|
22022
22236
|
</div>
|
22023
22237
|
</file>
|
22024
22238
|
<file name="script.js">
|
22025
|
-
|
22026
|
-
|
22027
|
-
|
22028
|
-
|
22239
|
+
angular.module('switchExample', ['ngAnimate'])
|
22240
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
22241
|
+
$scope.items = ['settings', 'home', 'other'];
|
22242
|
+
$scope.selection = $scope.items[0];
|
22243
|
+
}]);
|
22029
22244
|
</file>
|
22030
22245
|
<file name="animations.css">
|
22031
22246
|
.animate-switch-container {
|
@@ -22068,11 +22283,11 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
|
|
22068
22283
|
expect(switchElem.getText()).toMatch(/Settings Div/);
|
22069
22284
|
});
|
22070
22285
|
it('should change to home', function() {
|
22071
|
-
select.
|
22286
|
+
select.all(by.css('option')).get(1).click();
|
22072
22287
|
expect(switchElem.getText()).toMatch(/Home Span/);
|
22073
22288
|
});
|
22074
22289
|
it('should select default', function() {
|
22075
|
-
select.
|
22290
|
+
select.all(by.css('option')).get(2).click();
|
22076
22291
|
expect(switchElem.getText()).toMatch(/default/);
|
22077
22292
|
});
|
22078
22293
|
</file>
|
@@ -22164,15 +22379,10 @@ var ngSwitchDefaultDirective = ngDirective({
|
|
22164
22379
|
* @element ANY
|
22165
22380
|
*
|
22166
22381
|
* @example
|
22167
|
-
<example module="
|
22382
|
+
<example module="transcludeExample">
|
22168
22383
|
<file name="index.html">
|
22169
22384
|
<script>
|
22170
|
-
|
22171
|
-
$scope.title = 'Lorem Ipsum';
|
22172
|
-
$scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
|
22173
|
-
}
|
22174
|
-
|
22175
|
-
angular.module('transclude', [])
|
22385
|
+
angular.module('transcludeExample', [])
|
22176
22386
|
.directive('pane', function(){
|
22177
22387
|
return {
|
22178
22388
|
restrict: 'E',
|
@@ -22183,9 +22393,13 @@ var ngSwitchDefaultDirective = ngDirective({
|
|
22183
22393
|
'<div ng-transclude></div>' +
|
22184
22394
|
'</div>'
|
22185
22395
|
};
|
22186
|
-
})
|
22396
|
+
})
|
22397
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
22398
|
+
$scope.title = 'Lorem Ipsum';
|
22399
|
+
$scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
|
22400
|
+
}]);
|
22187
22401
|
</script>
|
22188
|
-
<div ng-controller="
|
22402
|
+
<div ng-controller="ExampleController">
|
22189
22403
|
<input ng-model="title"><br>
|
22190
22404
|
<textarea ng-model="text"></textarea> <br/>
|
22191
22405
|
<pane title="{{title}}">{{text}}</pane>
|
@@ -22344,21 +22558,22 @@ var ngOptionsMinErr = minErr('ngOptions');
|
|
22344
22558
|
* `value` variable (e.g. `value.propertyName`).
|
22345
22559
|
*
|
22346
22560
|
* @example
|
22347
|
-
<example>
|
22561
|
+
<example module="selectExample">
|
22348
22562
|
<file name="index.html">
|
22349
22563
|
<script>
|
22350
|
-
|
22351
|
-
$scope
|
22352
|
-
|
22353
|
-
|
22354
|
-
|
22355
|
-
|
22356
|
-
|
22357
|
-
|
22358
|
-
|
22359
|
-
|
22564
|
+
angular.module('selectExample', [])
|
22565
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
22566
|
+
$scope.colors = [
|
22567
|
+
{name:'black', shade:'dark'},
|
22568
|
+
{name:'white', shade:'light'},
|
22569
|
+
{name:'red', shade:'dark'},
|
22570
|
+
{name:'blue', shade:'dark'},
|
22571
|
+
{name:'yellow', shade:'light'}
|
22572
|
+
];
|
22573
|
+
$scope.myColor = $scope.colors[2]; // red
|
22574
|
+
}]);
|
22360
22575
|
</script>
|
22361
|
-
<div ng-controller="
|
22576
|
+
<div ng-controller="ExampleController">
|
22362
22577
|
<ul>
|
22363
22578
|
<li ng-repeat="color in colors">
|
22364
22579
|
Name: <input ng-model="color.name">
|
@@ -22395,7 +22610,7 @@ var ngOptionsMinErr = minErr('ngOptions');
|
|
22395
22610
|
<file name="protractor.js" type="protractor">
|
22396
22611
|
it('should check ng-options', function() {
|
22397
22612
|
expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');
|
22398
|
-
element.all(by.
|
22613
|
+
element.all(by.model('myColor')).first().click();
|
22399
22614
|
element.all(by.css('select[ng-model="myColor"] option')).first().click();
|
22400
22615
|
expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');
|
22401
22616
|
element(by.css('.nullable select[ng-model="myColor"]')).click();
|
@@ -22435,7 +22650,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
22435
22650
|
};
|
22436
22651
|
|
22437
22652
|
|
22438
|
-
self.addOption = function(value) {
|
22653
|
+
self.addOption = function(value, element) {
|
22439
22654
|
assertNotHasOwnProperty(value, '"option value"');
|
22440
22655
|
optionsMap[value] = true;
|
22441
22656
|
|
@@ -22443,6 +22658,12 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
22443
22658
|
$element.val(value);
|
22444
22659
|
if (unknownOption.parent()) unknownOption.remove();
|
22445
22660
|
}
|
22661
|
+
// Workaround for https://code.google.com/p/chromium/issues/detail?id=381459
|
22662
|
+
// Adding an <option selected="selected"> element to a <select required="required"> should
|
22663
|
+
// automatically select the new element
|
22664
|
+
if (element[0].hasAttribute('selected')) {
|
22665
|
+
element[0].selected = true;
|
22666
|
+
}
|
22446
22667
|
};
|
22447
22668
|
|
22448
22669
|
|
@@ -22896,10 +23117,10 @@ var optionDirective = ['$interpolate', function($interpolate) {
|
|
22896
23117
|
if (oldVal !== newVal) {
|
22897
23118
|
selectCtrl.removeOption(oldVal);
|
22898
23119
|
}
|
22899
|
-
selectCtrl.addOption(newVal);
|
23120
|
+
selectCtrl.addOption(newVal, element);
|
22900
23121
|
});
|
22901
23122
|
} else {
|
22902
|
-
selectCtrl.addOption(attr.value);
|
23123
|
+
selectCtrl.addOption(attr.value, element);
|
22903
23124
|
}
|
22904
23125
|
|
22905
23126
|
element.on('$destroy', function() {
|