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