angularjs-rails 1.4.8 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/angularjs-rails/version.rb +2 -2
- data/vendor/assets/javascripts/angular-animate.js +477 -286
- data/vendor/assets/javascripts/angular-aria.js +51 -51
- data/vendor/assets/javascripts/angular-cookies.js +9 -8
- data/vendor/assets/javascripts/angular-loader.js +45 -4
- data/vendor/assets/javascripts/angular-message-format.js +2 -2
- data/vendor/assets/javascripts/angular-messages.js +7 -5
- data/vendor/assets/javascripts/angular-mocks.js +406 -35
- data/vendor/assets/javascripts/angular-resource.js +121 -37
- data/vendor/assets/javascripts/angular-route.js +36 -11
- data/vendor/assets/javascripts/angular-sanitize.js +280 -246
- data/vendor/assets/javascripts/angular-scenario.js +2183 -773
- data/vendor/assets/javascripts/angular-touch.js +115 -14
- data/vendor/assets/javascripts/angular.js +2183 -773
- data/vendor/assets/javascripts/unstable/angular2-polyfills.js +3316 -0
- data/vendor/assets/javascripts/unstable/angular2.js +19327 -25066
- metadata +15 -14
@@ -9190,8 +9190,8 @@ return jQuery;
|
|
9190
9190
|
}));
|
9191
9191
|
|
9192
9192
|
/**
|
9193
|
-
* @license AngularJS v1.
|
9194
|
-
* (c) 2010-
|
9193
|
+
* @license AngularJS v1.5.0
|
9194
|
+
* (c) 2010-2016 Google, Inc. http://angularjs.org
|
9195
9195
|
* License: MIT
|
9196
9196
|
*/
|
9197
9197
|
(function(window, document){
|
@@ -9249,7 +9249,7 @@ function minErr(module, ErrorConstructor) {
|
|
9249
9249
|
return match;
|
9250
9250
|
});
|
9251
9251
|
|
9252
|
-
message += '\nhttp://errors.angularjs.org/1.
|
9252
|
+
message += '\nhttp://errors.angularjs.org/1.5.0/' +
|
9253
9253
|
(module ? module + '/' : '') + code;
|
9254
9254
|
|
9255
9255
|
for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
|
@@ -9380,29 +9380,9 @@ var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
|
|
9380
9380
|
// This is used so that it's possible for internal tests to create mock ValidityStates.
|
9381
9381
|
var VALIDITY_STATE_PROPERTY = 'validity';
|
9382
9382
|
|
9383
|
-
/**
|
9384
|
-
* @ngdoc function
|
9385
|
-
* @name angular.lowercase
|
9386
|
-
* @module ng
|
9387
|
-
* @kind function
|
9388
|
-
*
|
9389
|
-
* @description Converts the specified string to lowercase.
|
9390
|
-
* @param {string} string String to be converted to lowercase.
|
9391
|
-
* @returns {string} Lowercased string.
|
9392
|
-
*/
|
9393
|
-
var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
|
9394
9383
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
9395
9384
|
|
9396
|
-
|
9397
|
-
* @ngdoc function
|
9398
|
-
* @name angular.uppercase
|
9399
|
-
* @module ng
|
9400
|
-
* @kind function
|
9401
|
-
*
|
9402
|
-
* @description Converts the specified string to uppercase.
|
9403
|
-
* @param {string} string String to be converted to uppercase.
|
9404
|
-
* @returns {string} Uppercased string.
|
9405
|
-
*/
|
9385
|
+
var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
|
9406
9386
|
var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};
|
9407
9387
|
|
9408
9388
|
|
@@ -9422,7 +9402,7 @@ var manualUppercase = function(s) {
|
|
9422
9402
|
|
9423
9403
|
// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
|
9424
9404
|
// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
|
9425
|
-
// with correct but slower alternatives.
|
9405
|
+
// with correct but slower alternatives. See https://github.com/angular/angular.js/issues/11387
|
9426
9406
|
if ('i' !== 'I'.toLowerCase()) {
|
9427
9407
|
lowercase = manualLowercase;
|
9428
9408
|
uppercase = manualUppercase;
|
@@ -9465,7 +9445,7 @@ function isArrayLike(obj) {
|
|
9465
9445
|
|
9466
9446
|
// arrays, strings and jQuery/jqLite objects are array like
|
9467
9447
|
// * jqLite is either the jQuery or jqLite constructor function
|
9468
|
-
// * we have to check the
|
9448
|
+
// * we have to check the existence of jqLite first as this method is called
|
9469
9449
|
// via the forEach method when constructing the jqLite object in the first place
|
9470
9450
|
if (isArray(obj) || isString(obj) || (jqLite && obj instanceof jqLite)) return true;
|
9471
9451
|
|
@@ -9476,7 +9456,8 @@ function isArrayLike(obj) {
|
|
9476
9456
|
// NodeList objects (with `item` method) and
|
9477
9457
|
// other objects with suitable length characteristics are array-like
|
9478
9458
|
return isNumber(length) &&
|
9479
|
-
(length >= 0 && (length - 1) in obj || typeof obj.item == 'function');
|
9459
|
+
(length >= 0 && ((length - 1) in obj || obj instanceof Array) || typeof obj.item == 'function');
|
9460
|
+
|
9480
9461
|
}
|
9481
9462
|
|
9482
9463
|
/**
|
@@ -9573,7 +9554,7 @@ function forEachSorted(obj, iterator, context) {
|
|
9573
9554
|
* @returns {function(*, string)}
|
9574
9555
|
*/
|
9575
9556
|
function reverseParams(iteratorFn) {
|
9576
|
-
return function(value, key) {
|
9557
|
+
return function(value, key) {iteratorFn(key, value);};
|
9577
9558
|
}
|
9578
9559
|
|
9579
9560
|
/**
|
@@ -9944,6 +9925,10 @@ function isTypedArray(value) {
|
|
9944
9925
|
return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value));
|
9945
9926
|
}
|
9946
9927
|
|
9928
|
+
function isArrayBuffer(obj) {
|
9929
|
+
return toString.call(obj) === '[object ArrayBuffer]';
|
9930
|
+
}
|
9931
|
+
|
9947
9932
|
|
9948
9933
|
var trim = function(value) {
|
9949
9934
|
return isString(value) ? value.trim() : value;
|
@@ -9981,7 +9966,7 @@ function isElement(node) {
|
|
9981
9966
|
* @returns {object} in the form of {key1:true, key2:true, ...}
|
9982
9967
|
*/
|
9983
9968
|
function makeMap(str) {
|
9984
|
-
var obj = {}, items = str.split(
|
9969
|
+
var obj = {}, items = str.split(','), i;
|
9985
9970
|
for (i = 0; i < items.length; i++) {
|
9986
9971
|
obj[items[i]] = true;
|
9987
9972
|
}
|
@@ -10068,7 +10053,7 @@ function copy(source, destination) {
|
|
10068
10053
|
var stackDest = [];
|
10069
10054
|
|
10070
10055
|
if (destination) {
|
10071
|
-
if (isTypedArray(destination)) {
|
10056
|
+
if (isTypedArray(destination) || isArrayBuffer(destination)) {
|
10072
10057
|
throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated.");
|
10073
10058
|
}
|
10074
10059
|
if (source === destination) {
|
@@ -10142,22 +10127,10 @@ function copy(source, destination) {
|
|
10142
10127
|
}
|
10143
10128
|
|
10144
10129
|
var needsRecurse = false;
|
10145
|
-
var destination;
|
10130
|
+
var destination = copyType(source);
|
10146
10131
|
|
10147
|
-
if (
|
10148
|
-
destination = [];
|
10149
|
-
needsRecurse = true;
|
10150
|
-
} else if (isTypedArray(source)) {
|
10151
|
-
destination = new source.constructor(source);
|
10152
|
-
} else if (isDate(source)) {
|
10153
|
-
destination = new Date(source.getTime());
|
10154
|
-
} else if (isRegExp(source)) {
|
10155
|
-
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
|
10156
|
-
destination.lastIndex = source.lastIndex;
|
10157
|
-
} else if (isFunction(source.cloneNode)) {
|
10158
|
-
destination = source.cloneNode(true);
|
10159
|
-
} else {
|
10160
|
-
destination = Object.create(getPrototypeOf(source));
|
10132
|
+
if (destination === undefined) {
|
10133
|
+
destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
|
10161
10134
|
needsRecurse = true;
|
10162
10135
|
}
|
10163
10136
|
|
@@ -10168,6 +10141,45 @@ function copy(source, destination) {
|
|
10168
10141
|
? copyRecurse(source, destination)
|
10169
10142
|
: destination;
|
10170
10143
|
}
|
10144
|
+
|
10145
|
+
function copyType(source) {
|
10146
|
+
switch (toString.call(source)) {
|
10147
|
+
case '[object Int8Array]':
|
10148
|
+
case '[object Int16Array]':
|
10149
|
+
case '[object Int32Array]':
|
10150
|
+
case '[object Float32Array]':
|
10151
|
+
case '[object Float64Array]':
|
10152
|
+
case '[object Uint8Array]':
|
10153
|
+
case '[object Uint8ClampedArray]':
|
10154
|
+
case '[object Uint16Array]':
|
10155
|
+
case '[object Uint32Array]':
|
10156
|
+
return new source.constructor(copyElement(source.buffer));
|
10157
|
+
|
10158
|
+
case '[object ArrayBuffer]':
|
10159
|
+
//Support: IE10
|
10160
|
+
if (!source.slice) {
|
10161
|
+
var copied = new ArrayBuffer(source.byteLength);
|
10162
|
+
new Uint8Array(copied).set(new Uint8Array(source));
|
10163
|
+
return copied;
|
10164
|
+
}
|
10165
|
+
return source.slice(0);
|
10166
|
+
|
10167
|
+
case '[object Boolean]':
|
10168
|
+
case '[object Number]':
|
10169
|
+
case '[object String]':
|
10170
|
+
case '[object Date]':
|
10171
|
+
return new source.constructor(source.valueOf());
|
10172
|
+
|
10173
|
+
case '[object RegExp]':
|
10174
|
+
var re = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
|
10175
|
+
re.lastIndex = source.lastIndex;
|
10176
|
+
return re;
|
10177
|
+
}
|
10178
|
+
|
10179
|
+
if (isFunction(source.cloneNode)) {
|
10180
|
+
return source.cloneNode(true);
|
10181
|
+
}
|
10182
|
+
}
|
10171
10183
|
}
|
10172
10184
|
|
10173
10185
|
/**
|
@@ -10230,38 +10242,37 @@ function equals(o1, o2) {
|
|
10230
10242
|
if (o1 === null || o2 === null) return false;
|
10231
10243
|
if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
|
10232
10244
|
var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
|
10233
|
-
if (t1 == t2) {
|
10234
|
-
if (
|
10235
|
-
if (isArray(
|
10236
|
-
|
10237
|
-
|
10238
|
-
for (key = 0; key < length; key++) {
|
10239
|
-
if (!equals(o1[key], o2[key])) return false;
|
10240
|
-
}
|
10241
|
-
return true;
|
10242
|
-
}
|
10243
|
-
} else if (isDate(o1)) {
|
10244
|
-
if (!isDate(o2)) return false;
|
10245
|
-
return equals(o1.getTime(), o2.getTime());
|
10246
|
-
} else if (isRegExp(o1)) {
|
10247
|
-
return isRegExp(o2) ? o1.toString() == o2.toString() : false;
|
10248
|
-
} else {
|
10249
|
-
if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
|
10250
|
-
isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
|
10251
|
-
keySet = createMap();
|
10252
|
-
for (key in o1) {
|
10253
|
-
if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
|
10245
|
+
if (t1 == t2 && t1 == 'object') {
|
10246
|
+
if (isArray(o1)) {
|
10247
|
+
if (!isArray(o2)) return false;
|
10248
|
+
if ((length = o1.length) == o2.length) {
|
10249
|
+
for (key = 0; key < length; key++) {
|
10254
10250
|
if (!equals(o1[key], o2[key])) return false;
|
10255
|
-
keySet[key] = true;
|
10256
|
-
}
|
10257
|
-
for (key in o2) {
|
10258
|
-
if (!(key in keySet) &&
|
10259
|
-
key.charAt(0) !== '$' &&
|
10260
|
-
isDefined(o2[key]) &&
|
10261
|
-
!isFunction(o2[key])) return false;
|
10262
10251
|
}
|
10263
10252
|
return true;
|
10264
10253
|
}
|
10254
|
+
} else if (isDate(o1)) {
|
10255
|
+
if (!isDate(o2)) return false;
|
10256
|
+
return equals(o1.getTime(), o2.getTime());
|
10257
|
+
} else if (isRegExp(o1)) {
|
10258
|
+
if (!isRegExp(o2)) return false;
|
10259
|
+
return o1.toString() == o2.toString();
|
10260
|
+
} else {
|
10261
|
+
if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
|
10262
|
+
isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
|
10263
|
+
keySet = createMap();
|
10264
|
+
for (key in o1) {
|
10265
|
+
if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
|
10266
|
+
if (!equals(o1[key], o2[key])) return false;
|
10267
|
+
keySet[key] = true;
|
10268
|
+
}
|
10269
|
+
for (key in o2) {
|
10270
|
+
if (!(key in keySet) &&
|
10271
|
+
key.charAt(0) !== '$' &&
|
10272
|
+
isDefined(o2[key]) &&
|
10273
|
+
!isFunction(o2[key])) return false;
|
10274
|
+
}
|
10275
|
+
return true;
|
10265
10276
|
}
|
10266
10277
|
}
|
10267
10278
|
return false;
|
@@ -10438,7 +10449,7 @@ function toJsonReplacer(key, value) {
|
|
10438
10449
|
* @returns {string|undefined} JSON-ified string representing `obj`.
|
10439
10450
|
*/
|
10440
10451
|
function toJson(obj, pretty) {
|
10441
|
-
if (
|
10452
|
+
if (isUndefined(obj)) return undefined;
|
10442
10453
|
if (!isNumber(pretty)) {
|
10443
10454
|
pretty = pretty ? 2 : null;
|
10444
10455
|
}
|
@@ -10465,7 +10476,10 @@ function fromJson(json) {
|
|
10465
10476
|
}
|
10466
10477
|
|
10467
10478
|
|
10479
|
+
var ALL_COLONS = /:/g;
|
10468
10480
|
function timezoneToOffset(timezone, fallback) {
|
10481
|
+
// IE/Edge do not "understand" colon (`:`) in timezone
|
10482
|
+
timezone = timezone.replace(ALL_COLONS, '');
|
10469
10483
|
var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
|
10470
10484
|
return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
|
10471
10485
|
}
|
@@ -10480,8 +10494,9 @@ function addDateMinutes(date, minutes) {
|
|
10480
10494
|
|
10481
10495
|
function convertTimezoneToLocal(date, timezone, reverse) {
|
10482
10496
|
reverse = reverse ? -1 : 1;
|
10483
|
-
var
|
10484
|
-
|
10497
|
+
var dateTimezoneOffset = date.getTimezoneOffset();
|
10498
|
+
var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
|
10499
|
+
return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset));
|
10485
10500
|
}
|
10486
10501
|
|
10487
10502
|
|
@@ -10500,7 +10515,7 @@ function startingTag(element) {
|
|
10500
10515
|
return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :
|
10501
10516
|
elemHtml.
|
10502
10517
|
match(/^(<[^>]+>)/)[1].
|
10503
|
-
replace(/^<([\w\-]+)/, function(match, nodeName) {
|
10518
|
+
replace(/^<([\w\-]+)/, function(match, nodeName) {return '<' + lowercase(nodeName);});
|
10504
10519
|
} catch (e) {
|
10505
10520
|
return lowercase(elemHtml);
|
10506
10521
|
}
|
@@ -10943,7 +10958,6 @@ function snake_case(name, separator) {
|
|
10943
10958
|
}
|
10944
10959
|
|
10945
10960
|
var bindJQueryFired = false;
|
10946
|
-
var skipDestroyOnNextJQueryCleanData;
|
10947
10961
|
function bindJQuery() {
|
10948
10962
|
var originalCleanData;
|
10949
10963
|
|
@@ -10977,15 +10991,11 @@ function bindJQuery() {
|
|
10977
10991
|
originalCleanData = jQuery.cleanData;
|
10978
10992
|
jQuery.cleanData = function(elems) {
|
10979
10993
|
var events;
|
10980
|
-
|
10981
|
-
|
10982
|
-
|
10983
|
-
|
10984
|
-
jQuery(elem).triggerHandler('$destroy');
|
10985
|
-
}
|
10994
|
+
for (var i = 0, elem; (elem = elems[i]) != null; i++) {
|
10995
|
+
events = jQuery._data(elem, "events");
|
10996
|
+
if (events && events.$destroy) {
|
10997
|
+
jQuery(elem).triggerHandler('$destroy');
|
10986
10998
|
}
|
10987
|
-
} else {
|
10988
|
-
skipDestroyOnNextJQueryCleanData = false;
|
10989
10999
|
}
|
10990
11000
|
originalCleanData(elems);
|
10991
11001
|
};
|
@@ -11179,7 +11189,7 @@ function setupModuleLoader(window) {
|
|
11179
11189
|
* unspecified then the module is being retrieved for further configuration.
|
11180
11190
|
* @param {Function=} configFn Optional configuration function for the module. Same as
|
11181
11191
|
* {@link angular.Module#config Module#config()}.
|
11182
|
-
* @returns {
|
11192
|
+
* @returns {angular.Module} new module with the {@link angular.Module} api.
|
11183
11193
|
*/
|
11184
11194
|
return function module(name, requires, configFn) {
|
11185
11195
|
var assertNotHasOwnProperty = function(name, context) {
|
@@ -11385,6 +11395,19 @@ function setupModuleLoader(window) {
|
|
11385
11395
|
*/
|
11386
11396
|
directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'),
|
11387
11397
|
|
11398
|
+
/**
|
11399
|
+
* @ngdoc method
|
11400
|
+
* @name angular.Module#component
|
11401
|
+
* @module ng
|
11402
|
+
* @param {string} name Name of the component in camel-case (i.e. myComp which will match as my-comp)
|
11403
|
+
* @param {Object} options Component definition object (a simplified
|
11404
|
+
* {@link ng.$compile#directive-definition-object directive definition object})
|
11405
|
+
*
|
11406
|
+
* @description
|
11407
|
+
* See {@link ng.$compileProvider#component $compileProvider.component()}.
|
11408
|
+
*/
|
11409
|
+
component: invokeLaterAndSetModuleName('$compileProvider', 'component'),
|
11410
|
+
|
11388
11411
|
/**
|
11389
11412
|
* @ngdoc method
|
11390
11413
|
* @name angular.Module#config
|
@@ -11536,11 +11559,14 @@ function toDebugString(obj) {
|
|
11536
11559
|
$AnchorScrollProvider,
|
11537
11560
|
$AnimateProvider,
|
11538
11561
|
$CoreAnimateCssProvider,
|
11562
|
+
$$CoreAnimateJsProvider,
|
11539
11563
|
$$CoreAnimateQueueProvider,
|
11540
|
-
$$
|
11564
|
+
$$AnimateRunnerFactoryProvider,
|
11565
|
+
$$AnimateAsyncRunFactoryProvider,
|
11541
11566
|
$BrowserProvider,
|
11542
11567
|
$CacheFactoryProvider,
|
11543
11568
|
$ControllerProvider,
|
11569
|
+
$DateProvider,
|
11544
11570
|
$DocumentProvider,
|
11545
11571
|
$ExceptionHandlerProvider,
|
11546
11572
|
$FilterProvider,
|
@@ -11590,11 +11616,11 @@ function toDebugString(obj) {
|
|
11590
11616
|
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
|
11591
11617
|
*/
|
11592
11618
|
var version = {
|
11593
|
-
full: '1.
|
11619
|
+
full: '1.5.0', // all of these placeholder strings will be replaced by grunt's
|
11594
11620
|
major: 1, // package task
|
11595
|
-
minor:
|
11596
|
-
dot:
|
11597
|
-
codeName: '
|
11621
|
+
minor: 5,
|
11622
|
+
dot: 0,
|
11623
|
+
codeName: 'ennoblement-facilitation'
|
11598
11624
|
};
|
11599
11625
|
|
11600
11626
|
|
@@ -11696,8 +11722,10 @@ function publishExternalAPI(angular) {
|
|
11696
11722
|
$anchorScroll: $AnchorScrollProvider,
|
11697
11723
|
$animate: $AnimateProvider,
|
11698
11724
|
$animateCss: $CoreAnimateCssProvider,
|
11725
|
+
$$animateJs: $$CoreAnimateJsProvider,
|
11699
11726
|
$$animateQueue: $$CoreAnimateQueueProvider,
|
11700
|
-
$$AnimateRunner: $$
|
11727
|
+
$$AnimateRunner: $$AnimateRunnerFactoryProvider,
|
11728
|
+
$$animateAsyncRun: $$AnimateAsyncRunFactoryProvider,
|
11701
11729
|
$browser: $BrowserProvider,
|
11702
11730
|
$cacheFactory: $CacheFactoryProvider,
|
11703
11731
|
$controller: $ControllerProvider,
|
@@ -11768,16 +11796,22 @@ function publishExternalAPI(angular) {
|
|
11768
11796
|
*
|
11769
11797
|
* If jQuery is available, `angular.element` is an alias for the
|
11770
11798
|
* [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`
|
11771
|
-
* delegates to Angular's built-in subset of jQuery, called "jQuery lite" or
|
11799
|
+
* delegates to Angular's built-in subset of jQuery, called "jQuery lite" or **jqLite**.
|
11772
11800
|
*
|
11773
|
-
*
|
11774
|
-
* Angular to manipulate the DOM in a cross-browser compatible way.
|
11775
|
-
* commonly needed functionality with the goal of having a very small footprint
|
11801
|
+
* jqLite is a tiny, API-compatible subset of jQuery that allows
|
11802
|
+
* Angular to manipulate the DOM in a cross-browser compatible way. jqLite implements only the most
|
11803
|
+
* commonly needed functionality with the goal of having a very small footprint.
|
11776
11804
|
*
|
11777
|
-
* To use `jQuery`, simply ensure it is loaded before the `angular.js` file.
|
11805
|
+
* To use `jQuery`, simply ensure it is loaded before the `angular.js` file. You can also use the
|
11806
|
+
* {@link ngJq `ngJq`} directive to specify that jqlite should be used over jQuery, or to use a
|
11807
|
+
* specific version of jQuery if multiple versions exist on the page.
|
11778
11808
|
*
|
11779
|
-
* <div class="alert">**Note:**
|
11780
|
-
* jqLite
|
11809
|
+
* <div class="alert alert-info">**Note:** All element references in Angular are always wrapped with jQuery or
|
11810
|
+
* jqLite (such as the element argument in a directive's compile / link function). They are never raw DOM references.</div>
|
11811
|
+
*
|
11812
|
+
* <div class="alert alert-warning">**Note:** Keep in mind that this function will not find elements
|
11813
|
+
* by tag name / CSS selector. For lookups by tag name, try instead `angular.element(document).find(...)`
|
11814
|
+
* or `$document.find()`, or use the standard DOM APIs, e.g. `document.querySelectorAll()`.</div>
|
11781
11815
|
*
|
11782
11816
|
* ## Angular's jqLite
|
11783
11817
|
* jqLite provides only the following jQuery methods:
|
@@ -11790,7 +11824,8 @@ function publishExternalAPI(angular) {
|
|
11790
11824
|
* - [`children()`](http://api.jquery.com/children/) - Does not support selectors
|
11791
11825
|
* - [`clone()`](http://api.jquery.com/clone/)
|
11792
11826
|
* - [`contents()`](http://api.jquery.com/contents/)
|
11793
|
-
* - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`.
|
11827
|
+
* - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`.
|
11828
|
+
* As a setter, does not convert numbers to strings or append 'px', and also does not have automatic property prefixing.
|
11794
11829
|
* - [`data()`](http://api.jquery.com/data/)
|
11795
11830
|
* - [`detach()`](http://api.jquery.com/detach/)
|
11796
11831
|
* - [`empty()`](http://api.jquery.com/empty/)
|
@@ -11924,6 +11959,12 @@ function jqLiteHasData(node) {
|
|
11924
11959
|
return false;
|
11925
11960
|
}
|
11926
11961
|
|
11962
|
+
function jqLiteCleanData(nodes) {
|
11963
|
+
for (var i = 0, ii = nodes.length; i < ii; i++) {
|
11964
|
+
jqLiteRemoveData(nodes[i]);
|
11965
|
+
}
|
11966
|
+
}
|
11967
|
+
|
11927
11968
|
function jqLiteBuildFragment(html, context) {
|
11928
11969
|
var tmp, tag, wrap,
|
11929
11970
|
fragment = context.createDocumentFragment(),
|
@@ -11976,6 +12017,16 @@ function jqLiteParseHTML(html, context) {
|
|
11976
12017
|
return [];
|
11977
12018
|
}
|
11978
12019
|
|
12020
|
+
function jqLiteWrapNode(node, wrapper) {
|
12021
|
+
var parent = node.parentNode;
|
12022
|
+
|
12023
|
+
if (parent) {
|
12024
|
+
parent.replaceChild(wrapper, node);
|
12025
|
+
}
|
12026
|
+
|
12027
|
+
wrapper.appendChild(node);
|
12028
|
+
}
|
12029
|
+
|
11979
12030
|
|
11980
12031
|
// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
|
11981
12032
|
var jqLiteContains = Node.prototype.contains || function(arg) {
|
@@ -12226,7 +12277,7 @@ function jqLiteRemove(element, keepData) {
|
|
12226
12277
|
function jqLiteDocumentLoaded(action, win) {
|
12227
12278
|
win = win || window;
|
12228
12279
|
if (win.document.readyState === 'complete') {
|
12229
|
-
// Force the action to be run async for consistent
|
12280
|
+
// Force the action to be run async for consistent behavior
|
12230
12281
|
// from the action's point of view
|
12231
12282
|
// i.e. it will definitely not be in a $apply
|
12232
12283
|
win.setTimeout(action);
|
@@ -12312,7 +12363,8 @@ function getAliasedAttrName(name) {
|
|
12312
12363
|
forEach({
|
12313
12364
|
data: jqLiteData,
|
12314
12365
|
removeData: jqLiteRemoveData,
|
12315
|
-
hasData: jqLiteHasData
|
12366
|
+
hasData: jqLiteHasData,
|
12367
|
+
cleanData: jqLiteCleanData
|
12316
12368
|
}, function(fn, name) {
|
12317
12369
|
JQLite[name] = fn;
|
12318
12370
|
});
|
@@ -12667,12 +12719,7 @@ forEach({
|
|
12667
12719
|
},
|
12668
12720
|
|
12669
12721
|
wrap: function(element, wrapNode) {
|
12670
|
-
|
12671
|
-
var parent = element.parentNode;
|
12672
|
-
if (parent) {
|
12673
|
-
parent.replaceChild(wrapNode, element);
|
12674
|
-
}
|
12675
|
-
wrapNode.appendChild(element);
|
12722
|
+
jqLiteWrapNode(element, jqLite(wrapNode).eq(0).clone()[0]);
|
12676
12723
|
},
|
12677
12724
|
|
12678
12725
|
remove: jqLiteRemove,
|
@@ -12950,17 +12997,23 @@ var $$HashMapProvider = [function() {
|
|
12950
12997
|
* Implicit module which gets automatically added to each {@link auto.$injector $injector}.
|
12951
12998
|
*/
|
12952
12999
|
|
13000
|
+
var ARROW_ARG = /^([^\(]+?)=>/;
|
12953
13001
|
var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m;
|
12954
13002
|
var FN_ARG_SPLIT = /,/;
|
12955
13003
|
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
|
12956
13004
|
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
|
12957
13005
|
var $injectorMinErr = minErr('$injector');
|
12958
13006
|
|
13007
|
+
function extractArgs(fn) {
|
13008
|
+
var fnText = fn.toString().replace(STRIP_COMMENTS, ''),
|
13009
|
+
args = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);
|
13010
|
+
return args;
|
13011
|
+
}
|
13012
|
+
|
12959
13013
|
function anonFn(fn) {
|
12960
13014
|
// For anonymous functions, showing at the very least the function signature can help in
|
12961
13015
|
// debugging.
|
12962
|
-
var
|
12963
|
-
args = fnText.match(FN_ARGS);
|
13016
|
+
var args = extractArgs(fn);
|
12964
13017
|
if (args) {
|
12965
13018
|
return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')';
|
12966
13019
|
}
|
@@ -12969,7 +13022,6 @@ function anonFn(fn) {
|
|
12969
13022
|
|
12970
13023
|
function annotate(fn, strictDi, name) {
|
12971
13024
|
var $inject,
|
12972
|
-
fnText,
|
12973
13025
|
argDecl,
|
12974
13026
|
last;
|
12975
13027
|
|
@@ -12984,8 +13036,7 @@ function annotate(fn, strictDi, name) {
|
|
12984
13036
|
throw $injectorMinErr('strictdi',
|
12985
13037
|
'{0} is not using explicit annotation and cannot be invoked in strict mode', name);
|
12986
13038
|
}
|
12987
|
-
|
12988
|
-
argDecl = fnText.match(FN_ARGS);
|
13039
|
+
argDecl = extractArgs(fn);
|
12989
13040
|
forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {
|
12990
13041
|
arg.replace(FN_ARG, function(all, underscore, name) {
|
12991
13042
|
$inject.push(name);
|
@@ -13375,8 +13426,20 @@ function annotate(fn, strictDi, name) {
|
|
13375
13426
|
*
|
13376
13427
|
* Register a **service constructor**, which will be invoked with `new` to create the service
|
13377
13428
|
* instance.
|
13378
|
-
* This is short for registering a service where its provider's `$get` property is
|
13379
|
-
*
|
13429
|
+
* This is short for registering a service where its provider's `$get` property is a factory
|
13430
|
+
* function that returns an instance instantiated by the injector from the service constructor
|
13431
|
+
* function.
|
13432
|
+
*
|
13433
|
+
* Internally it looks a bit like this:
|
13434
|
+
*
|
13435
|
+
* ```
|
13436
|
+
* {
|
13437
|
+
* $get: function() {
|
13438
|
+
* return $injector.instantiate(constructor);
|
13439
|
+
* }
|
13440
|
+
* }
|
13441
|
+
* ```
|
13442
|
+
*
|
13380
13443
|
*
|
13381
13444
|
* You should use {@link auto.$provide#service $provide.service(class)} if you define your service
|
13382
13445
|
* as a type/class.
|
@@ -13477,7 +13540,7 @@ function annotate(fn, strictDi, name) {
|
|
13477
13540
|
* @description
|
13478
13541
|
*
|
13479
13542
|
* Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator
|
13480
|
-
* intercepts the creation of a service, allowing it to override or modify the
|
13543
|
+
* intercepts the creation of a service, allowing it to override or modify the behavior of the
|
13481
13544
|
* service. The object returned by the decorator may be the original service, or a new service
|
13482
13545
|
* object which replaces or wraps and delegates to the original service.
|
13483
13546
|
*
|
@@ -13526,14 +13589,19 @@ function createInjector(modulesToLoad, strictDi) {
|
|
13526
13589
|
throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
|
13527
13590
|
})),
|
13528
13591
|
instanceCache = {},
|
13529
|
-
|
13592
|
+
protoInstanceInjector =
|
13530
13593
|
createInternalInjector(instanceCache, function(serviceName, caller) {
|
13531
13594
|
var provider = providerInjector.get(serviceName + providerSuffix, caller);
|
13532
|
-
return instanceInjector.invoke(
|
13533
|
-
|
13534
|
-
|
13595
|
+
return instanceInjector.invoke(
|
13596
|
+
provider.$get, provider, undefined, serviceName);
|
13597
|
+
}),
|
13598
|
+
instanceInjector = protoInstanceInjector;
|
13535
13599
|
|
13536
|
-
|
13600
|
+
providerCache['$injector' + providerSuffix] = { $get: valueFn(protoInstanceInjector) };
|
13601
|
+
var runBlocks = loadModules(modulesToLoad);
|
13602
|
+
instanceInjector = protoInstanceInjector.get('$injector');
|
13603
|
+
instanceInjector.strictDi = strictDi;
|
13604
|
+
forEach(runBlocks, function(fn) { if (fn) instanceInjector.invoke(fn); });
|
13537
13605
|
|
13538
13606
|
return instanceInjector;
|
13539
13607
|
|
@@ -13683,48 +13751,67 @@ function createInjector(modulesToLoad, strictDi) {
|
|
13683
13751
|
}
|
13684
13752
|
}
|
13685
13753
|
|
13686
|
-
function invoke(fn, self, locals, serviceName) {
|
13687
|
-
if (typeof locals === 'string') {
|
13688
|
-
serviceName = locals;
|
13689
|
-
locals = null;
|
13690
|
-
}
|
13691
13754
|
|
13755
|
+
function injectionArgs(fn, locals, serviceName) {
|
13692
13756
|
var args = [],
|
13693
|
-
$inject = createInjector.$$annotate(fn, strictDi, serviceName)
|
13694
|
-
length, i,
|
13695
|
-
key;
|
13757
|
+
$inject = createInjector.$$annotate(fn, strictDi, serviceName);
|
13696
13758
|
|
13697
|
-
for (i = 0, length = $inject.length; i < length; i++) {
|
13698
|
-
key = $inject[i];
|
13759
|
+
for (var i = 0, length = $inject.length; i < length; i++) {
|
13760
|
+
var key = $inject[i];
|
13699
13761
|
if (typeof key !== 'string') {
|
13700
13762
|
throw $injectorMinErr('itkn',
|
13701
13763
|
'Incorrect injection token! Expected service name as string, got {0}', key);
|
13702
13764
|
}
|
13703
|
-
args.push(
|
13704
|
-
|
13705
|
-
|
13706
|
-
|
13707
|
-
|
13765
|
+
args.push(locals && locals.hasOwnProperty(key) ? locals[key] :
|
13766
|
+
getService(key, serviceName));
|
13767
|
+
}
|
13768
|
+
return args;
|
13769
|
+
}
|
13770
|
+
|
13771
|
+
function isClass(func) {
|
13772
|
+
// IE 9-11 do not support classes and IE9 leaks with the code below.
|
13773
|
+
if (msie <= 11) {
|
13774
|
+
return false;
|
13775
|
+
}
|
13776
|
+
// Workaround for MS Edge.
|
13777
|
+
// Check https://connect.microsoft.com/IE/Feedback/Details/2211653
|
13778
|
+
return typeof func === 'function'
|
13779
|
+
&& /^(?:class\s|constructor\()/.test(Function.prototype.toString.call(func));
|
13780
|
+
}
|
13781
|
+
|
13782
|
+
function invoke(fn, self, locals, serviceName) {
|
13783
|
+
if (typeof locals === 'string') {
|
13784
|
+
serviceName = locals;
|
13785
|
+
locals = null;
|
13708
13786
|
}
|
13787
|
+
|
13788
|
+
var args = injectionArgs(fn, locals, serviceName);
|
13709
13789
|
if (isArray(fn)) {
|
13710
|
-
fn = fn[length];
|
13790
|
+
fn = fn[fn.length - 1];
|
13711
13791
|
}
|
13712
13792
|
|
13713
|
-
|
13714
|
-
|
13715
|
-
|
13793
|
+
if (!isClass(fn)) {
|
13794
|
+
// http://jsperf.com/angularjs-invoke-apply-vs-switch
|
13795
|
+
// #5388
|
13796
|
+
return fn.apply(self, args);
|
13797
|
+
} else {
|
13798
|
+
args.unshift(null);
|
13799
|
+
return new (Function.prototype.bind.apply(fn, args))();
|
13800
|
+
}
|
13716
13801
|
}
|
13717
13802
|
|
13803
|
+
|
13718
13804
|
function instantiate(Type, locals, serviceName) {
|
13719
13805
|
// Check if Type is annotated and use just the given function at n-1 as parameter
|
13720
13806
|
// e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
|
13721
|
-
|
13722
|
-
var
|
13723
|
-
|
13724
|
-
|
13725
|
-
return
|
13807
|
+
var ctor = (isArray(Type) ? Type[Type.length - 1] : Type);
|
13808
|
+
var args = injectionArgs(Type, locals, serviceName);
|
13809
|
+
// Empty object at position 0 is ignored for invocation with `new`, but required.
|
13810
|
+
args.unshift(null);
|
13811
|
+
return new (Function.prototype.bind.apply(ctor, args))();
|
13726
13812
|
}
|
13727
13813
|
|
13814
|
+
|
13728
13815
|
return {
|
13729
13816
|
invoke: invoke,
|
13730
13817
|
instantiate: instantiate,
|
@@ -14063,27 +14150,8 @@ function prepareAnimateOptions(options) {
|
|
14063
14150
|
: {};
|
14064
14151
|
}
|
14065
14152
|
|
14066
|
-
var $$
|
14067
|
-
this.$get =
|
14068
|
-
function AnimateRunner() {}
|
14069
|
-
AnimateRunner.all = noop;
|
14070
|
-
AnimateRunner.chain = noop;
|
14071
|
-
AnimateRunner.prototype = {
|
14072
|
-
end: noop,
|
14073
|
-
cancel: noop,
|
14074
|
-
resume: noop,
|
14075
|
-
pause: noop,
|
14076
|
-
complete: noop,
|
14077
|
-
then: function(pass, fail) {
|
14078
|
-
return $q(function(resolve) {
|
14079
|
-
$$rAF(function() {
|
14080
|
-
resolve();
|
14081
|
-
});
|
14082
|
-
}).then(pass, fail);
|
14083
|
-
}
|
14084
|
-
};
|
14085
|
-
return AnimateRunner;
|
14086
|
-
}];
|
14153
|
+
var $$CoreAnimateJsProvider = function() {
|
14154
|
+
this.$get = function() {};
|
14087
14155
|
};
|
14088
14156
|
|
14089
14157
|
// this is prefixed with Core since it conflicts with
|
@@ -14111,7 +14179,12 @@ var $$CoreAnimateQueueProvider = function() {
|
|
14111
14179
|
addRemoveClassesPostDigest(element, options.addClass, options.removeClass);
|
14112
14180
|
}
|
14113
14181
|
|
14114
|
-
|
14182
|
+
var runner = new $$AnimateRunner(); // jshint ignore:line
|
14183
|
+
|
14184
|
+
// since there are no animations to run the runner needs to be
|
14185
|
+
// notified that the animation call is complete.
|
14186
|
+
runner.complete();
|
14187
|
+
return runner;
|
14115
14188
|
}
|
14116
14189
|
};
|
14117
14190
|
|
@@ -14353,8 +14426,8 @@ var $AnimateProvider = ['$provide', function($provide) {
|
|
14353
14426
|
* // remove all the animation event listeners listening for `enter` on the given element and its children
|
14354
14427
|
* $animate.off('enter', container);
|
14355
14428
|
*
|
14356
|
-
* // remove the event listener function provided by `
|
14357
|
-
* // to listen for `enter` on the given `
|
14429
|
+
* // remove the event listener function provided by `callback` that is set
|
14430
|
+
* // to listen for `enter` on the given `container` as well as its children
|
14358
14431
|
* $animate.off('enter', container, callback);
|
14359
14432
|
* ```
|
14360
14433
|
*
|
@@ -14576,17 +14649,30 @@ var $AnimateProvider = ['$provide', function($provide) {
|
|
14576
14649
|
* @kind function
|
14577
14650
|
*
|
14578
14651
|
* @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element.
|
14579
|
-
* If any detected CSS transition, keyframe or JavaScript matches the provided className value then the animation will take
|
14580
|
-
* on the provided styles. For example, if a transition animation is set for the given
|
14581
|
-
* to styles will be applied alongside the given transition. If
|
14582
|
-
*
|
14652
|
+
* If any detected CSS transition, keyframe or JavaScript matches the provided className value, then the animation will take
|
14653
|
+
* on the provided styles. For example, if a transition animation is set for the given classNamem, then the provided `from` and
|
14654
|
+
* `to` styles will be applied alongside the given transition. If the CSS style provided in `from` does not have a corresponding
|
14655
|
+
* style in `to`, the style in `from` is applied immediately, and no animation is run.
|
14656
|
+
* If a JavaScript animation is detected then the provided styles will be given in as function parameters into the `animate`
|
14657
|
+
* method (or as part of the `options` parameter):
|
14658
|
+
*
|
14659
|
+
* ```js
|
14660
|
+
* ngModule.animation('.my-inline-animation', function() {
|
14661
|
+
* return {
|
14662
|
+
* animate : function(element, from, to, done, options) {
|
14663
|
+
* //animation
|
14664
|
+
* done();
|
14665
|
+
* }
|
14666
|
+
* }
|
14667
|
+
* });
|
14668
|
+
* ```
|
14583
14669
|
*
|
14584
14670
|
* @param {DOMElement} element the element which the CSS styles will be applied to
|
14585
14671
|
* @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation.
|
14586
14672
|
* @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation.
|
14587
14673
|
* @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If
|
14588
14674
|
* this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element.
|
14589
|
-
* (Note that if no animation is detected then this value will not be
|
14675
|
+
* (Note that if no animation is detected then this value will not be applied to the element.)
|
14590
14676
|
* @param {object=} options an optional collection of options/styles that will be applied to the element
|
14591
14677
|
*
|
14592
14678
|
* @return {Promise} the animation callback promise
|
@@ -14604,6 +14690,190 @@ var $AnimateProvider = ['$provide', function($provide) {
|
|
14604
14690
|
}];
|
14605
14691
|
}];
|
14606
14692
|
|
14693
|
+
var $$AnimateAsyncRunFactoryProvider = function() {
|
14694
|
+
this.$get = ['$$rAF', function($$rAF) {
|
14695
|
+
var waitQueue = [];
|
14696
|
+
|
14697
|
+
function waitForTick(fn) {
|
14698
|
+
waitQueue.push(fn);
|
14699
|
+
if (waitQueue.length > 1) return;
|
14700
|
+
$$rAF(function() {
|
14701
|
+
for (var i = 0; i < waitQueue.length; i++) {
|
14702
|
+
waitQueue[i]();
|
14703
|
+
}
|
14704
|
+
waitQueue = [];
|
14705
|
+
});
|
14706
|
+
}
|
14707
|
+
|
14708
|
+
return function() {
|
14709
|
+
var passed = false;
|
14710
|
+
waitForTick(function() {
|
14711
|
+
passed = true;
|
14712
|
+
});
|
14713
|
+
return function(callback) {
|
14714
|
+
passed ? callback() : waitForTick(callback);
|
14715
|
+
};
|
14716
|
+
};
|
14717
|
+
}];
|
14718
|
+
};
|
14719
|
+
|
14720
|
+
var $$AnimateRunnerFactoryProvider = function() {
|
14721
|
+
this.$get = ['$q', '$sniffer', '$$animateAsyncRun', '$document', '$timeout',
|
14722
|
+
function($q, $sniffer, $$animateAsyncRun, $document, $timeout) {
|
14723
|
+
|
14724
|
+
var INITIAL_STATE = 0;
|
14725
|
+
var DONE_PENDING_STATE = 1;
|
14726
|
+
var DONE_COMPLETE_STATE = 2;
|
14727
|
+
|
14728
|
+
AnimateRunner.chain = function(chain, callback) {
|
14729
|
+
var index = 0;
|
14730
|
+
|
14731
|
+
next();
|
14732
|
+
function next() {
|
14733
|
+
if (index === chain.length) {
|
14734
|
+
callback(true);
|
14735
|
+
return;
|
14736
|
+
}
|
14737
|
+
|
14738
|
+
chain[index](function(response) {
|
14739
|
+
if (response === false) {
|
14740
|
+
callback(false);
|
14741
|
+
return;
|
14742
|
+
}
|
14743
|
+
index++;
|
14744
|
+
next();
|
14745
|
+
});
|
14746
|
+
}
|
14747
|
+
};
|
14748
|
+
|
14749
|
+
AnimateRunner.all = function(runners, callback) {
|
14750
|
+
var count = 0;
|
14751
|
+
var status = true;
|
14752
|
+
forEach(runners, function(runner) {
|
14753
|
+
runner.done(onProgress);
|
14754
|
+
});
|
14755
|
+
|
14756
|
+
function onProgress(response) {
|
14757
|
+
status = status && response;
|
14758
|
+
if (++count === runners.length) {
|
14759
|
+
callback(status);
|
14760
|
+
}
|
14761
|
+
}
|
14762
|
+
};
|
14763
|
+
|
14764
|
+
function AnimateRunner(host) {
|
14765
|
+
this.setHost(host);
|
14766
|
+
|
14767
|
+
var rafTick = $$animateAsyncRun();
|
14768
|
+
var timeoutTick = function(fn) {
|
14769
|
+
$timeout(fn, 0, false);
|
14770
|
+
};
|
14771
|
+
|
14772
|
+
this._doneCallbacks = [];
|
14773
|
+
this._tick = function(fn) {
|
14774
|
+
var doc = $document[0];
|
14775
|
+
|
14776
|
+
// the document may not be ready or attached
|
14777
|
+
// to the module for some internal tests
|
14778
|
+
if (doc && doc.hidden) {
|
14779
|
+
timeoutTick(fn);
|
14780
|
+
} else {
|
14781
|
+
rafTick(fn);
|
14782
|
+
}
|
14783
|
+
};
|
14784
|
+
this._state = 0;
|
14785
|
+
}
|
14786
|
+
|
14787
|
+
AnimateRunner.prototype = {
|
14788
|
+
setHost: function(host) {
|
14789
|
+
this.host = host || {};
|
14790
|
+
},
|
14791
|
+
|
14792
|
+
done: function(fn) {
|
14793
|
+
if (this._state === DONE_COMPLETE_STATE) {
|
14794
|
+
fn();
|
14795
|
+
} else {
|
14796
|
+
this._doneCallbacks.push(fn);
|
14797
|
+
}
|
14798
|
+
},
|
14799
|
+
|
14800
|
+
progress: noop,
|
14801
|
+
|
14802
|
+
getPromise: function() {
|
14803
|
+
if (!this.promise) {
|
14804
|
+
var self = this;
|
14805
|
+
this.promise = $q(function(resolve, reject) {
|
14806
|
+
self.done(function(status) {
|
14807
|
+
status === false ? reject() : resolve();
|
14808
|
+
});
|
14809
|
+
});
|
14810
|
+
}
|
14811
|
+
return this.promise;
|
14812
|
+
},
|
14813
|
+
|
14814
|
+
then: function(resolveHandler, rejectHandler) {
|
14815
|
+
return this.getPromise().then(resolveHandler, rejectHandler);
|
14816
|
+
},
|
14817
|
+
|
14818
|
+
'catch': function(handler) {
|
14819
|
+
return this.getPromise()['catch'](handler);
|
14820
|
+
},
|
14821
|
+
|
14822
|
+
'finally': function(handler) {
|
14823
|
+
return this.getPromise()['finally'](handler);
|
14824
|
+
},
|
14825
|
+
|
14826
|
+
pause: function() {
|
14827
|
+
if (this.host.pause) {
|
14828
|
+
this.host.pause();
|
14829
|
+
}
|
14830
|
+
},
|
14831
|
+
|
14832
|
+
resume: function() {
|
14833
|
+
if (this.host.resume) {
|
14834
|
+
this.host.resume();
|
14835
|
+
}
|
14836
|
+
},
|
14837
|
+
|
14838
|
+
end: function() {
|
14839
|
+
if (this.host.end) {
|
14840
|
+
this.host.end();
|
14841
|
+
}
|
14842
|
+
this._resolve(true);
|
14843
|
+
},
|
14844
|
+
|
14845
|
+
cancel: function() {
|
14846
|
+
if (this.host.cancel) {
|
14847
|
+
this.host.cancel();
|
14848
|
+
}
|
14849
|
+
this._resolve(false);
|
14850
|
+
},
|
14851
|
+
|
14852
|
+
complete: function(response) {
|
14853
|
+
var self = this;
|
14854
|
+
if (self._state === INITIAL_STATE) {
|
14855
|
+
self._state = DONE_PENDING_STATE;
|
14856
|
+
self._tick(function() {
|
14857
|
+
self._resolve(response);
|
14858
|
+
});
|
14859
|
+
}
|
14860
|
+
},
|
14861
|
+
|
14862
|
+
_resolve: function(response) {
|
14863
|
+
if (this._state !== DONE_COMPLETE_STATE) {
|
14864
|
+
forEach(this._doneCallbacks, function(fn) {
|
14865
|
+
fn(response);
|
14866
|
+
});
|
14867
|
+
this._doneCallbacks.length = 0;
|
14868
|
+
this._state = DONE_COMPLETE_STATE;
|
14869
|
+
}
|
14870
|
+
}
|
14871
|
+
};
|
14872
|
+
|
14873
|
+
return AnimateRunner;
|
14874
|
+
}];
|
14875
|
+
};
|
14876
|
+
|
14607
14877
|
/**
|
14608
14878
|
* @ngdoc service
|
14609
14879
|
* @name $animateCss
|
@@ -14616,37 +14886,18 @@ var $AnimateProvider = ['$provide', function($provide) {
|
|
14616
14886
|
* Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}.
|
14617
14887
|
*/
|
14618
14888
|
var $CoreAnimateCssProvider = function() {
|
14619
|
-
this.$get = ['$$rAF', '$q', function($$rAF, $q) {
|
14889
|
+
this.$get = ['$$rAF', '$q', '$$AnimateRunner', function($$rAF, $q, $$AnimateRunner) {
|
14620
14890
|
|
14621
|
-
|
14622
|
-
|
14623
|
-
|
14624
|
-
|
14625
|
-
|
14626
|
-
|
14627
|
-
|
14628
|
-
|
14629
|
-
cancel: function() {
|
14630
|
-
this.done(true);
|
14631
|
-
},
|
14632
|
-
getPromise: function() {
|
14633
|
-
if (!this.defer) {
|
14634
|
-
this.defer = $q.defer();
|
14635
|
-
}
|
14636
|
-
return this.defer.promise;
|
14637
|
-
},
|
14638
|
-
then: function(f1,f2) {
|
14639
|
-
return this.getPromise().then(f1,f2);
|
14640
|
-
},
|
14641
|
-
'catch': function(f1) {
|
14642
|
-
return this.getPromise()['catch'](f1);
|
14643
|
-
},
|
14644
|
-
'finally': function(f1) {
|
14645
|
-
return this.getPromise()['finally'](f1);
|
14891
|
+
return function(element, initialOptions) {
|
14892
|
+
// all of the animation functions should create
|
14893
|
+
// a copy of the options data, however, if a
|
14894
|
+
// parent service has already created a copy then
|
14895
|
+
// we should stick to using that
|
14896
|
+
var options = initialOptions || {};
|
14897
|
+
if (!options.$$prepared) {
|
14898
|
+
options = copy(options);
|
14646
14899
|
}
|
14647
|
-
};
|
14648
14900
|
|
14649
|
-
return function(element, options) {
|
14650
14901
|
// there is no point in applying the styles since
|
14651
14902
|
// there is no animation that goes on at all in
|
14652
14903
|
// this version of $animateCss.
|
@@ -14659,7 +14910,8 @@ var $CoreAnimateCssProvider = function() {
|
|
14659
14910
|
options.from = null;
|
14660
14911
|
}
|
14661
14912
|
|
14662
|
-
|
14913
|
+
/* jshint newcap: false */
|
14914
|
+
var closed, runner = new $$AnimateRunner();
|
14663
14915
|
return {
|
14664
14916
|
start: run,
|
14665
14917
|
end: run
|
@@ -14667,16 +14919,16 @@ var $CoreAnimateCssProvider = function() {
|
|
14667
14919
|
|
14668
14920
|
function run() {
|
14669
14921
|
$$rAF(function() {
|
14670
|
-
|
14922
|
+
applyAnimationContents();
|
14671
14923
|
if (!closed) {
|
14672
|
-
runner.
|
14924
|
+
runner.complete();
|
14673
14925
|
}
|
14674
14926
|
closed = true;
|
14675
14927
|
});
|
14676
14928
|
return runner;
|
14677
14929
|
}
|
14678
14930
|
|
14679
|
-
function
|
14931
|
+
function applyAnimationContents() {
|
14680
14932
|
if (options.addClass) {
|
14681
14933
|
element.addClass(options.addClass);
|
14682
14934
|
options.addClass = null;
|
@@ -15584,7 +15836,7 @@ function $TemplateCacheProvider() {
|
|
15584
15836
|
* When this property is set to true, the HTML compiler will collect DOM nodes between
|
15585
15837
|
* nodes with the attributes `directive-name-start` and `directive-name-end`, and group them
|
15586
15838
|
* together as the directive elements. It is recommended that this feature be used on directives
|
15587
|
-
* which are not strictly
|
15839
|
+
* which are not strictly behavioral (such as {@link ngClick}), and which
|
15588
15840
|
* do not manipulate or replace child nodes (such as {@link ngInclude}).
|
15589
15841
|
*
|
15590
15842
|
* #### `priority`
|
@@ -15622,35 +15874,62 @@ function $TemplateCacheProvider() {
|
|
15622
15874
|
* is bound to the parent scope, via matching attributes on the directive's element:
|
15623
15875
|
*
|
15624
15876
|
* * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
|
15625
|
-
* always a string since DOM attributes are strings. If no `attr` name is specified
|
15626
|
-
* attribute name is assumed to be the same as the local name.
|
15627
|
-
*
|
15628
|
-
*
|
15629
|
-
*
|
15630
|
-
*
|
15631
|
-
*
|
15632
|
-
*
|
15633
|
-
*
|
15634
|
-
*
|
15635
|
-
* name
|
15636
|
-
*
|
15637
|
-
*
|
15877
|
+
* always a string since DOM attributes are strings. If no `attr` name is specified then the
|
15878
|
+
* attribute name is assumed to be the same as the local name. Given `<my-component
|
15879
|
+
* my-attr="hello {{name}}">` and the isolate scope definition `scope: { localName:'@myAttr' }`,
|
15880
|
+
* the directive's scope property `localName` will reflect the interpolated value of `hello
|
15881
|
+
* {{name}}`. As the `name` attribute changes so will the `localName` property on the directive's
|
15882
|
+
* scope. The `name` is read from the parent scope (not the directive's scope).
|
15883
|
+
*
|
15884
|
+
* * `=` or `=attr` - set up a bidirectional binding between a local scope property and an expression
|
15885
|
+
* passed via the attribute `attr`. The expression is evaluated in the context of the parent scope.
|
15886
|
+
* If no `attr` name is specified then the attribute name is assumed to be the same as the local
|
15887
|
+
* name. Given `<my-component my-attr="parentModel">` and the isolate scope definition `scope: {
|
15888
|
+
* localModel: '=myAttr' }`, the property `localModel` on the directive's scope will reflect the
|
15889
|
+
* value of `parentModel` on the parent scope. Changes to `parentModel` will be reflected in
|
15890
|
+
* `localModel` and vice versa. Optional attributes should be marked as such with a question mark:
|
15891
|
+
* `=?` or `=?attr`. If the binding expression is non-assignable, or if the attribute isn't
|
15892
|
+
* optional and doesn't exist, an exception ({@link error/$compile/nonassign `$compile:nonassign`})
|
15893
|
+
* will be thrown upon discovering changes to the local value, since it will be impossible to sync
|
15894
|
+
* them back to the parent scope. By default, the {@link ng.$rootScope.Scope#$watch `$watch`}
|
15895
|
+
* method is used for tracking changes, and the equality check is based on object identity.
|
15896
|
+
* However, if an object literal or an array literal is passed as the binding expression, the
|
15897
|
+
* equality check is done by value (using the {@link angular.equals} function). It's also possible
|
15898
|
+
* to watch the evaluated value shallowly with {@link ng.$rootScope.Scope#$watchCollection
|
15899
|
+
* `$watchCollection`}: use `=*` or `=*attr` (`=*?` or `=*?attr` if the attribute is optional).
|
15900
|
+
*
|
15901
|
+
* * `<` or `<attr` - set up a one-way (one-directional) binding between a local scope property and an
|
15902
|
+
* expression passed via the attribute `attr`. The expression is evaluated in the context of the
|
15903
|
+
* parent scope. If no `attr` name is specified then the attribute name is assumed to be the same as the
|
15904
|
+
* local name. You can also make the binding optional by adding `?`: `<?` or `<?attr`.
|
15905
|
+
*
|
15906
|
+
* For example, given `<my-component my-attr="parentModel">` and directive definition of
|
15907
|
+
* `scope: { localModel:'<myAttr' }`, then the isolated scope property `localModel` will reflect the
|
15638
15908
|
* value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
|
15639
|
-
* in `localModel
|
15640
|
-
*
|
15641
|
-
*
|
15642
|
-
*
|
15643
|
-
*
|
15644
|
-
*
|
15645
|
-
*
|
15646
|
-
*
|
15647
|
-
*
|
15648
|
-
*
|
15649
|
-
*
|
15650
|
-
*
|
15651
|
-
*
|
15652
|
-
*
|
15653
|
-
*
|
15909
|
+
* in `localModel`, but changes in `localModel` will not reflect in `parentModel`. There are however
|
15910
|
+
* two caveats:
|
15911
|
+
* 1. one-way binding does not copy the value from the parent to the isolate scope, it simply
|
15912
|
+
* sets the same value. That means if your bound value is an object, changes to its properties
|
15913
|
+
* in the isolated scope will be reflected in the parent scope (because both reference the same object).
|
15914
|
+
* 2. one-way binding watches changes to the **identity** of the parent value. That means the
|
15915
|
+
* {@link ng.$rootScope.Scope#$watch `$watch`} on the parent value only fires if the reference
|
15916
|
+
* to the value has changed. In most cases, this should not be of concern, but can be important
|
15917
|
+
* to know if you one-way bind to an object, and then replace that object in the isolated scope.
|
15918
|
+
* If you now change a property of the object in your parent scope, the change will not be
|
15919
|
+
* propagated to the isolated scope, because the identity of the object on the parent scope
|
15920
|
+
* has not changed. Instead you must assign a new object.
|
15921
|
+
*
|
15922
|
+
* One-way binding is useful if you do not plan to propagate changes to your isolated scope bindings
|
15923
|
+
* back to the parent. However, it does not make this completely impossible.
|
15924
|
+
*
|
15925
|
+
* * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope. If
|
15926
|
+
* no `attr` name is specified then the attribute name is assumed to be the same as the local name.
|
15927
|
+
* Given `<my-component my-attr="count = count + value">` and the isolate scope definition `scope: {
|
15928
|
+
* localFn:'&myAttr' }`, the isolate scope property `localFn` will point to a function wrapper for
|
15929
|
+
* the `count = count + value` expression. Often it's desirable to pass data from the isolated scope
|
15930
|
+
* via an expression to the parent scope. This can be done by passing a map of local variable names
|
15931
|
+
* and values into the expression wrapper fn. For example, if the expression is `increment(amount)`
|
15932
|
+
* then we can specify the amount value by calling the `localFn` as `localFn({amount: 22})`.
|
15654
15933
|
*
|
15655
15934
|
* In general it's possible to apply more than one directive to one element, but there might be limitations
|
15656
15935
|
* depending on the type of scope required by the directives. The following points will help explain these limitations.
|
@@ -15668,9 +15947,32 @@ function $TemplateCacheProvider() {
|
|
15668
15947
|
*
|
15669
15948
|
*
|
15670
15949
|
* #### `bindToController`
|
15671
|
-
*
|
15672
|
-
*
|
15673
|
-
*
|
15950
|
+
* This property is used to bind scope properties directly to the controller. It can be either
|
15951
|
+
* `true` or an object hash with the same format as the `scope` property. Additionally, a controller
|
15952
|
+
* alias must be set, either by using `controllerAs: 'myAlias'` or by specifying the alias in the controller
|
15953
|
+
* definition: `controller: 'myCtrl as myAlias'`.
|
15954
|
+
*
|
15955
|
+
* When an isolate scope is used for a directive (see above), `bindToController: true` will
|
15956
|
+
* allow a component to have its properties bound to the controller, rather than to scope.
|
15957
|
+
*
|
15958
|
+
* After the controller is instantiated, the initial values of the isolate scope bindings will be bound to the controller
|
15959
|
+
* properties. You can access these bindings once they have been initialized by providing a controller method called
|
15960
|
+
* `$onInit`, which is called after all the controllers on an element have been constructed and had their bindings
|
15961
|
+
* initialized.
|
15962
|
+
*
|
15963
|
+
* <div class="alert alert-warning">
|
15964
|
+
* **Deprecation warning:** although bindings for non-ES6 class controllers are currently
|
15965
|
+
* bound to `this` before the controller constructor is called, this use is now deprecated. Please place initialization
|
15966
|
+
* code that relies upon bindings inside a `$onInit` method on the controller, instead.
|
15967
|
+
* </div>
|
15968
|
+
*
|
15969
|
+
* It is also possible to set `bindToController` to an object hash with the same format as the `scope` property.
|
15970
|
+
* This will set up the scope bindings to the controller directly. Note that `scope` can still be used
|
15971
|
+
* to define which kind of scope is created. By default, no scope is created. Use `scope: {}` to create an isolate
|
15972
|
+
* scope (useful for component directives).
|
15973
|
+
*
|
15974
|
+
* If both `bindToController` and `scope` are defined and have object hashes, `bindToController` overrides `scope`.
|
15975
|
+
*
|
15674
15976
|
*
|
15675
15977
|
* #### `controller`
|
15676
15978
|
* Controller constructor function. The controller is instantiated before the
|
@@ -15682,10 +15984,10 @@ function $TemplateCacheProvider() {
|
|
15682
15984
|
* * `$element` - Current element
|
15683
15985
|
* * `$attrs` - Current attributes object for the element
|
15684
15986
|
* * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:
|
15685
|
-
* `function([scope], cloneLinkingFn, futureParentElement)
|
15686
|
-
* * `scope`: optional
|
15687
|
-
* * `cloneLinkingFn`: optional argument to create clones of the original transcluded content.
|
15688
|
-
* * `futureParentElement
|
15987
|
+
* `function([scope], cloneLinkingFn, futureParentElement, slotName)`:
|
15988
|
+
* * `scope`: (optional) override the scope.
|
15989
|
+
* * `cloneLinkingFn`: (optional) argument to create clones of the original transcluded content.
|
15990
|
+
* * `futureParentElement` (optional):
|
15689
15991
|
* * defines the parent to which the `cloneLinkingFn` will add the cloned elements.
|
15690
15992
|
* * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`.
|
15691
15993
|
* * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements)
|
@@ -15693,14 +15995,34 @@ function $TemplateCacheProvider() {
|
|
15693
15995
|
* as those elements need to created and cloned in a special way when they are defined outside their
|
15694
15996
|
* usual containers (e.g. like `<svg>`).
|
15695
15997
|
* * See also the `directive.templateNamespace` property.
|
15998
|
+
* * `slotName`: (optional) the name of the slot to transclude. If falsy (e.g. `null`, `undefined` or `''`)
|
15999
|
+
* then the default translusion is provided.
|
16000
|
+
* The `$transclude` function also has a method on it, `$transclude.isSlotFilled(slotName)`, which returns
|
16001
|
+
* `true` if the specified slot contains content (i.e. one or more DOM nodes).
|
15696
16002
|
*
|
16003
|
+
* The controller can provide the following methods that act as life-cycle hooks:
|
16004
|
+
* * `$onInit` - Called on each controller after all the controllers on an element have been constructed and
|
16005
|
+
* had their bindings initialized (and before the pre & post linking functions for the directives on
|
16006
|
+
* this element). This is a good place to put initialization code for your controller.
|
15697
16007
|
*
|
15698
16008
|
* #### `require`
|
15699
16009
|
* Require another directive and inject its controller as the fourth argument to the linking function. The
|
15700
|
-
* `require`
|
15701
|
-
*
|
15702
|
-
*
|
15703
|
-
*
|
16010
|
+
* `require` property can be a string, an array or an object:
|
16011
|
+
* * a **string** containing the name of the directive to pass to the linking function
|
16012
|
+
* * an **array** containing the names of directives to pass to the linking function. The argument passed to the
|
16013
|
+
* linking function will be an array of controllers in the same order as the names in the `require` property
|
16014
|
+
* * an **object** whose property values are the names of the directives to pass to the linking function. The argument
|
16015
|
+
* passed to the linking function will also be an object with matching keys, whose values will hold the corresponding
|
16016
|
+
* controllers.
|
16017
|
+
*
|
16018
|
+
* If the `require` property is an object and `bindToController` is truthy, then the required controllers are
|
16019
|
+
* bound to the controller using the keys of the `require` property. This binding occurs after all the controllers
|
16020
|
+
* have been constructed but before `$onInit` is called.
|
16021
|
+
* See the {@link $compileProvider#component} helper for an example of how this can be used.
|
16022
|
+
*
|
16023
|
+
* If no such required directive(s) can be found, or if the directive does not have a controller, then an error is
|
16024
|
+
* raised (unless no link function is specified and the required controllers are not being bound to the directive
|
16025
|
+
* controller, in which case error checking is skipped). The name can be prefixed with:
|
15704
16026
|
*
|
15705
16027
|
* * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
|
15706
16028
|
* * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
|
@@ -15793,14 +16115,6 @@ function $TemplateCacheProvider() {
|
|
15793
16115
|
* The contents are compiled and provided to the directive as a **transclusion function**. See the
|
15794
16116
|
* {@link $compile#transclusion Transclusion} section below.
|
15795
16117
|
*
|
15796
|
-
* There are two kinds of transclusion depending upon whether you want to transclude just the contents of the
|
15797
|
-
* directive's element or the entire element:
|
15798
|
-
*
|
15799
|
-
* * `true` - transclude the content (i.e. the child nodes) of the directive's element.
|
15800
|
-
* * `'element'` - transclude the whole of the directive's element including any directives on this
|
15801
|
-
* element that defined at a lower priority than this directive. When used, the `template`
|
15802
|
-
* property is ignored.
|
15803
|
-
*
|
15804
16118
|
*
|
15805
16119
|
* #### `compile`
|
15806
16120
|
*
|
@@ -15828,7 +16142,7 @@ function $TemplateCacheProvider() {
|
|
15828
16142
|
|
15829
16143
|
* <div class="alert alert-warning">
|
15830
16144
|
* **Note:** The compile function cannot handle directives that recursively use themselves in their
|
15831
|
-
* own templates or compile functions. Compiling these directives results in an infinite loop and
|
16145
|
+
* own templates or compile functions. Compiling these directives results in an infinite loop and
|
15832
16146
|
* stack overflow errors.
|
15833
16147
|
*
|
15834
16148
|
* This can be avoided by manually using $compile in the postLink function to imperatively compile
|
@@ -15930,6 +16244,34 @@ function $TemplateCacheProvider() {
|
|
15930
16244
|
* Testing Transclusion Directives}.
|
15931
16245
|
* </div>
|
15932
16246
|
*
|
16247
|
+
* There are three kinds of transclusion depending upon whether you want to transclude just the contents of the
|
16248
|
+
* directive's element, the entire element or multiple parts of the element contents:
|
16249
|
+
*
|
16250
|
+
* * `true` - transclude the content (i.e. the child nodes) of the directive's element.
|
16251
|
+
* * `'element'` - transclude the whole of the directive's element including any directives on this
|
16252
|
+
* element that defined at a lower priority than this directive. When used, the `template`
|
16253
|
+
* property is ignored.
|
16254
|
+
* * **`{...}` (an object hash):** - map elements of the content onto transclusion "slots" in the template.
|
16255
|
+
*
|
16256
|
+
* **Mult-slot transclusion** is declared by providing an object for the `transclude` property.
|
16257
|
+
*
|
16258
|
+
* This object is a map where the keys are the name of the slot to fill and the value is an element selector
|
16259
|
+
* used to match the HTML to the slot. The element selector should be in normalized form (e.g. `myElement`)
|
16260
|
+
* and will match the standard element variants (e.g. `my-element`, `my:element`, `data-my-element`, etc).
|
16261
|
+
*
|
16262
|
+
* For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}
|
16263
|
+
*
|
16264
|
+
* If the element selector is prefixed with a `?` then that slot is optional.
|
16265
|
+
*
|
16266
|
+
* For example, the transclude object `{ slotA: '?myCustomElement' }` maps `<my-custom-element>` elements to
|
16267
|
+
* the `slotA` slot, which can be accessed via the `$transclude` function or via the {@link ngTransclude} directive.
|
16268
|
+
*
|
16269
|
+
* Slots that are not marked as optional (`?`) will trigger a compile time error if there are no matching elements
|
16270
|
+
* in the transclude content. If you wish to know if an optional slot was filled with content, then you can call
|
16271
|
+
* `$transclude.isSlotFilled(slotName)` on the transclude function passed to the directive's link function and
|
16272
|
+
* injectable into the directive's controller.
|
16273
|
+
*
|
16274
|
+
*
|
15933
16275
|
* #### Transclusion Functions
|
15934
16276
|
*
|
15935
16277
|
* When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion
|
@@ -15950,7 +16292,7 @@ function $TemplateCacheProvider() {
|
|
15950
16292
|
* content and the `scope` is the newly created transclusion scope, to which the clone is bound.
|
15951
16293
|
*
|
15952
16294
|
* <div class="alert alert-info">
|
15953
|
-
* **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a
|
16295
|
+
* **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a transclude function
|
15954
16296
|
* since you then get a fresh clone of the original DOM and also have access to the new transclusion scope.
|
15955
16297
|
* </div>
|
15956
16298
|
*
|
@@ -15982,7 +16324,7 @@ function $TemplateCacheProvider() {
|
|
15982
16324
|
* </div>
|
15983
16325
|
*
|
15984
16326
|
* The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat}
|
15985
|
-
* automatically destroy their
|
16327
|
+
* automatically destroy their transcluded clones as necessary so you do not need to worry about this if
|
15986
16328
|
* you are simply using {@link ngTransclude} to inject the transclusion into your directive.
|
15987
16329
|
*
|
15988
16330
|
*
|
@@ -16007,19 +16349,19 @@ function $TemplateCacheProvider() {
|
|
16007
16349
|
*
|
16008
16350
|
* The `$parent` scope hierarchy will look like this:
|
16009
16351
|
*
|
16010
|
-
|
16011
|
-
|
16012
|
-
|
16013
|
-
|
16014
|
-
|
16352
|
+
```
|
16353
|
+
- $rootScope
|
16354
|
+
- isolate
|
16355
|
+
- transclusion
|
16356
|
+
```
|
16015
16357
|
*
|
16016
16358
|
* but the scopes will inherit prototypically from different scopes to their `$parent`.
|
16017
16359
|
*
|
16018
|
-
|
16019
|
-
|
16020
|
-
|
16021
|
-
|
16022
|
-
|
16360
|
+
```
|
16361
|
+
- $rootScope
|
16362
|
+
- transclusion
|
16363
|
+
- isolate
|
16364
|
+
```
|
16023
16365
|
*
|
16024
16366
|
*
|
16025
16367
|
* ### Attributes
|
@@ -16027,10 +16369,9 @@ function $TemplateCacheProvider() {
|
|
16027
16369
|
* The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the
|
16028
16370
|
* `link()` or `compile()` functions. It has a variety of uses.
|
16029
16371
|
*
|
16030
|
-
*
|
16031
|
-
*
|
16032
|
-
* the attributes
|
16033
|
-
* the attributes.
|
16372
|
+
* * *Accessing normalized attribute names:* Directives like 'ngBind' can be expressed in many ways:
|
16373
|
+
* 'ng:bind', `data-ng-bind`, or 'x-ng-bind'. The attributes object allows for normalized access
|
16374
|
+
* to the attributes.
|
16034
16375
|
*
|
16035
16376
|
* * *Directive inter-communication:* All directives share the same instance of the attributes
|
16036
16377
|
* object which allows the directives to use the attributes object as inter directive
|
@@ -16151,8 +16492,15 @@ function $TemplateCacheProvider() {
|
|
16151
16492
|
* directives; if given, it will be passed through to the link functions of
|
16152
16493
|
* directives found in `element` during compilation.
|
16153
16494
|
* * `transcludeControllers` - an object hash with keys that map controller names
|
16154
|
-
* to
|
16155
|
-
* available to directives
|
16495
|
+
* to a hash with the key `instance`, which maps to the controller instance;
|
16496
|
+
* if given, it will make the controllers available to directives on the compileNode:
|
16497
|
+
* ```
|
16498
|
+
* {
|
16499
|
+
* parent: {
|
16500
|
+
* instance: parentControllerInstance
|
16501
|
+
* }
|
16502
|
+
* }
|
16503
|
+
* ```
|
16156
16504
|
* * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add
|
16157
16505
|
* the cloned elements; only needed for transcludes that are allowed to contain non html
|
16158
16506
|
* elements (e.g. SVG elements). See also the directive.controller property.
|
@@ -16213,7 +16561,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
16213
16561
|
var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
|
16214
16562
|
|
16215
16563
|
function parseIsolateBindings(scope, directiveName, isController) {
|
16216
|
-
var LOCAL_REGEXP = /^\s*([
|
16564
|
+
var LOCAL_REGEXP = /^\s*([@&<]|=(\*?))(\??)\s*(\w*)\s*$/;
|
16217
16565
|
|
16218
16566
|
var bindings = {};
|
16219
16567
|
|
@@ -16300,8 +16648,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
16300
16648
|
* @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which
|
16301
16649
|
* will match as <code>ng-bind</code>), or an object map of directives where the keys are the
|
16302
16650
|
* names and the values are the factories.
|
16303
|
-
* @param {Function|Array} directiveFactory An injectable directive factory function. See
|
16304
|
-
* {@link guide/directive} for more info.
|
16651
|
+
* @param {Function|Array} directiveFactory An injectable directive factory function. See the
|
16652
|
+
* {@link guide/directive directive guide} and the {@link $compile compile API} for more info.
|
16305
16653
|
* @returns {ng.$compileProvider} Self for chaining.
|
16306
16654
|
*/
|
16307
16655
|
this.directive = function registerDirective(name, directiveFactory) {
|
@@ -16348,6 +16696,128 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
16348
16696
|
return this;
|
16349
16697
|
};
|
16350
16698
|
|
16699
|
+
/**
|
16700
|
+
* @ngdoc method
|
16701
|
+
* @name $compileProvider#component
|
16702
|
+
* @module ng
|
16703
|
+
* @param {string} name Name of the component in camelCase (i.e. `myComp` which will match `<my-comp>`)
|
16704
|
+
* @param {Object} options Component definition object (a simplified
|
16705
|
+
* {@link ng.$compile#directive-definition-object directive definition object}),
|
16706
|
+
* with the following properties (all optional):
|
16707
|
+
*
|
16708
|
+
* - `controller` – `{(string|function()=}` – controller constructor function that should be
|
16709
|
+
* associated with newly created scope or the name of a {@link ng.$compile#-controller-
|
16710
|
+
* registered controller} if passed as a string. An empty `noop` function by default.
|
16711
|
+
* - `controllerAs` – `{string=}` – identifier name for to reference the controller in the component's scope.
|
16712
|
+
* If present, the controller will be published to scope under the `controllerAs` name.
|
16713
|
+
* If not present, this will default to be `$ctrl`.
|
16714
|
+
* - `template` – `{string=|function()=}` – html template as a string or a function that
|
16715
|
+
* returns an html template as a string which should be used as the contents of this component.
|
16716
|
+
* Empty string by default.
|
16717
|
+
*
|
16718
|
+
* If `template` is a function, then it is {@link auto.$injector#invoke injected} with
|
16719
|
+
* the following locals:
|
16720
|
+
*
|
16721
|
+
* - `$element` - Current element
|
16722
|
+
* - `$attrs` - Current attributes object for the element
|
16723
|
+
*
|
16724
|
+
* - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
|
16725
|
+
* template that should be used as the contents of this component.
|
16726
|
+
*
|
16727
|
+
* If `templateUrl` is a function, then it is {@link auto.$injector#invoke injected} with
|
16728
|
+
* the following locals:
|
16729
|
+
*
|
16730
|
+
* - `$element` - Current element
|
16731
|
+
* - `$attrs` - Current attributes object for the element
|
16732
|
+
*
|
16733
|
+
* - `bindings` – `{object=}` – defines bindings between DOM attributes and component properties.
|
16734
|
+
* Component properties are always bound to the component controller and not to the scope.
|
16735
|
+
* See {@link ng.$compile#-bindtocontroller- `bindToController`}.
|
16736
|
+
* - `transclude` – `{boolean=}` – whether {@link $compile#transclusion content transclusion} is enabled.
|
16737
|
+
* Disabled by default.
|
16738
|
+
* - `$...` – `{function()=}` – additional annotations to provide to the directive factory function.
|
16739
|
+
*
|
16740
|
+
* @returns {ng.$compileProvider} the compile provider itself, for chaining of function calls.
|
16741
|
+
* @description
|
16742
|
+
* Register a **component definition** with the compiler. This is a shorthand for registering a special
|
16743
|
+
* type of directive, which represents a self-contained UI component in your application. Such components
|
16744
|
+
* are always isolated (i.e. `scope: {}`) and are always restricted to elements (i.e. `restrict: 'E'`).
|
16745
|
+
*
|
16746
|
+
* Component definitions are very simple and do not require as much configuration as defining general
|
16747
|
+
* directives. Component definitions usually consist only of a template and a controller backing it.
|
16748
|
+
*
|
16749
|
+
* In order to make the definition easier, components enforce best practices like use of `controllerAs`,
|
16750
|
+
* `bindToController`. They always have **isolate scope** and are restricted to elements.
|
16751
|
+
*
|
16752
|
+
* Here are a few examples of how you would usually define components:
|
16753
|
+
*
|
16754
|
+
* ```js
|
16755
|
+
* var myMod = angular.module(...);
|
16756
|
+
* myMod.component('myComp', {
|
16757
|
+
* template: '<div>My name is {{$ctrl.name}}</div>',
|
16758
|
+
* controller: function() {
|
16759
|
+
* this.name = 'shahar';
|
16760
|
+
* }
|
16761
|
+
* });
|
16762
|
+
*
|
16763
|
+
* myMod.component('myComp', {
|
16764
|
+
* template: '<div>My name is {{$ctrl.name}}</div>',
|
16765
|
+
* bindings: {name: '@'}
|
16766
|
+
* });
|
16767
|
+
*
|
16768
|
+
* myMod.component('myComp', {
|
16769
|
+
* templateUrl: 'views/my-comp.html',
|
16770
|
+
* controller: 'MyCtrl as ctrl',
|
16771
|
+
* bindings: {name: '@'}
|
16772
|
+
* });
|
16773
|
+
*
|
16774
|
+
* ```
|
16775
|
+
* For more examples, and an in-depth guide, see the {@link guide/component component guide}.
|
16776
|
+
*
|
16777
|
+
* <br />
|
16778
|
+
* See also {@link ng.$compileProvider#directive $compileProvider.directive()}.
|
16779
|
+
*/
|
16780
|
+
this.component = function registerComponent(name, options) {
|
16781
|
+
var controller = options.controller || function() {};
|
16782
|
+
|
16783
|
+
function factory($injector) {
|
16784
|
+
function makeInjectable(fn) {
|
16785
|
+
if (isFunction(fn) || isArray(fn)) {
|
16786
|
+
return function(tElement, tAttrs) {
|
16787
|
+
return $injector.invoke(fn, this, {$element: tElement, $attrs: tAttrs});
|
16788
|
+
};
|
16789
|
+
} else {
|
16790
|
+
return fn;
|
16791
|
+
}
|
16792
|
+
}
|
16793
|
+
|
16794
|
+
var template = (!options.template && !options.templateUrl ? '' : options.template);
|
16795
|
+
return {
|
16796
|
+
controller: controller,
|
16797
|
+
controllerAs: identifierForController(options.controller) || options.controllerAs || '$ctrl',
|
16798
|
+
template: makeInjectable(template),
|
16799
|
+
templateUrl: makeInjectable(options.templateUrl),
|
16800
|
+
transclude: options.transclude,
|
16801
|
+
scope: {},
|
16802
|
+
bindToController: options.bindings || {},
|
16803
|
+
restrict: 'E',
|
16804
|
+
require: options.require
|
16805
|
+
};
|
16806
|
+
}
|
16807
|
+
|
16808
|
+
// Copy any annotation properties (starting with $) over to the factory function
|
16809
|
+
// These could be used by libraries such as the new component router
|
16810
|
+
forEach(options, function(val, key) {
|
16811
|
+
if (key.charAt(0) === '$') {
|
16812
|
+
factory[key] = val;
|
16813
|
+
}
|
16814
|
+
});
|
16815
|
+
|
16816
|
+
factory.$inject = ['$injector'];
|
16817
|
+
|
16818
|
+
return this.directive(name, factory);
|
16819
|
+
};
|
16820
|
+
|
16351
16821
|
|
16352
16822
|
/**
|
16353
16823
|
* @ngdoc method
|
@@ -16441,10 +16911,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
16441
16911
|
|
16442
16912
|
this.$get = [
|
16443
16913
|
'$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',
|
16444
|
-
'$controller', '$rootScope', '$
|
16914
|
+
'$controller', '$rootScope', '$sce', '$animate', '$$sanitizeUri',
|
16445
16915
|
function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse,
|
16446
|
-
$controller, $rootScope, $
|
16916
|
+
$controller, $rootScope, $sce, $animate, $$sanitizeUri) {
|
16447
16917
|
|
16918
|
+
var SIMPLE_ATTR_NAME = /^\w/;
|
16919
|
+
var specialAttrHolder = document.createElement('div');
|
16448
16920
|
var Attributes = function(element, attributesToCopy) {
|
16449
16921
|
if (attributesToCopy) {
|
16450
16922
|
var keys = Object.keys(attributesToCopy);
|
@@ -16580,7 +17052,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
16580
17052
|
|
16581
17053
|
nodeName = nodeName_(this.$$element);
|
16582
17054
|
|
16583
|
-
if ((nodeName === 'a' && key === 'href') ||
|
17055
|
+
if ((nodeName === 'a' && (key === 'href' || key === 'xlinkHref')) ||
|
16584
17056
|
(nodeName === 'img' && key === 'src')) {
|
16585
17057
|
// sanitize a[href] and img[src] values
|
16586
17058
|
this[key] = value = $$sanitizeUri(value, key === 'src');
|
@@ -16624,7 +17096,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
16624
17096
|
if (value === null || isUndefined(value)) {
|
16625
17097
|
this.$$element.removeAttr(attrName);
|
16626
17098
|
} else {
|
16627
|
-
|
17099
|
+
if (SIMPLE_ATTR_NAME.test(attrName)) {
|
17100
|
+
this.$$element.attr(attrName, value);
|
17101
|
+
} else {
|
17102
|
+
setSpecialAttr(this.$$element[0], attrName, value);
|
17103
|
+
}
|
16628
17104
|
}
|
16629
17105
|
}
|
16630
17106
|
|
@@ -16655,7 +17131,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
16655
17131
|
* @param {string} key Normalized key. (ie ngAttribute) .
|
16656
17132
|
* @param {function(interpolatedValue)} fn Function that will be called whenever
|
16657
17133
|
the interpolated value of the attribute changes.
|
16658
|
-
* See the {@link guide/
|
17134
|
+
* See the {@link guide/interpolation#how-text-and-attribute-bindings-work Interpolation
|
17135
|
+
* guide} for more info.
|
16659
17136
|
* @returns {function()} Returns a deregistration function for this observer.
|
16660
17137
|
*/
|
16661
17138
|
$observe: function(key, fn) {
|
@@ -16677,6 +17154,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
16677
17154
|
}
|
16678
17155
|
};
|
16679
17156
|
|
17157
|
+
function setSpecialAttr(element, attrName, value) {
|
17158
|
+
// Attributes names that do not start with letters (such as `(click)`) cannot be set using `setAttribute`
|
17159
|
+
// so we have to jump through some hoops to get such an attribute
|
17160
|
+
// https://github.com/angular/angular.js/pull/13318
|
17161
|
+
specialAttrHolder.innerHTML = "<span " + attrName + ">";
|
17162
|
+
var attributes = specialAttrHolder.firstChild.attributes;
|
17163
|
+
var attribute = attributes[0];
|
17164
|
+
// We have to remove the attribute from its container element before we can add it to the destination element
|
17165
|
+
attributes.removeNamedItem(attribute.name);
|
17166
|
+
attribute.value = value;
|
17167
|
+
element.attributes.setNamedItem(attribute);
|
17168
|
+
}
|
16680
17169
|
|
16681
17170
|
function safeAddClass($element, className) {
|
16682
17171
|
try {
|
@@ -16690,7 +17179,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
16690
17179
|
|
16691
17180
|
var startSymbol = $interpolate.startSymbol(),
|
16692
17181
|
endSymbol = $interpolate.endSymbol(),
|
16693
|
-
denormalizeTemplate = (startSymbol == '{{'
|
17182
|
+
denormalizeTemplate = (startSymbol == '{{' && endSymbol == '}}')
|
16694
17183
|
? identity
|
16695
17184
|
: function denormalizeTemplate(template) {
|
16696
17185
|
return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
|
@@ -16734,13 +17223,19 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
16734
17223
|
// modify it.
|
16735
17224
|
$compileNodes = jqLite($compileNodes);
|
16736
17225
|
}
|
17226
|
+
|
17227
|
+
var NOT_EMPTY = /\S+/;
|
17228
|
+
|
16737
17229
|
// We can not compile top level text elements since text nodes can be merged and we will
|
16738
17230
|
// not be able to attach scope data to them, so we will wrap them in <span>
|
16739
|
-
|
16740
|
-
|
16741
|
-
|
17231
|
+
for (var i = 0, len = $compileNodes.length; i < len; i++) {
|
17232
|
+
var domNode = $compileNodes[i];
|
17233
|
+
|
17234
|
+
if (domNode.nodeType === NODE_TYPE_TEXT && domNode.nodeValue.match(NOT_EMPTY) /* non-empty */) {
|
17235
|
+
jqLiteWrapNode(domNode, $compileNodes[i] = document.createElement('span'));
|
16742
17236
|
}
|
16743
|
-
}
|
17237
|
+
}
|
17238
|
+
|
16744
17239
|
var compositeLinkFn =
|
16745
17240
|
compileNodes($compileNodes, transcludeFn, $compileNodes,
|
16746
17241
|
maxPriority, ignoreDirective, previousCompileContext);
|
@@ -16811,7 +17306,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
16811
17306
|
if (!node) {
|
16812
17307
|
return 'html';
|
16813
17308
|
} else {
|
16814
|
-
return nodeName_(node) !== 'foreignobject' &&
|
17309
|
+
return nodeName_(node) !== 'foreignobject' && toString.call(node).match(/SVG/) ? 'svg' : 'html';
|
16815
17310
|
}
|
16816
17311
|
}
|
16817
17312
|
|
@@ -16945,6 +17440,17 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
16945
17440
|
});
|
16946
17441
|
};
|
16947
17442
|
|
17443
|
+
// We need to attach the transclusion slots onto the `boundTranscludeFn`
|
17444
|
+
// so that they are available inside the `controllersBoundTransclude` function
|
17445
|
+
var boundSlots = boundTranscludeFn.$$slots = createMap();
|
17446
|
+
for (var slotName in transcludeFn.$$slots) {
|
17447
|
+
if (transcludeFn.$$slots[slotName]) {
|
17448
|
+
boundSlots[slotName] = createBoundTranscludeFn(scope, transcludeFn.$$slots[slotName], previousBoundTranscludeFn);
|
17449
|
+
} else {
|
17450
|
+
boundSlots[slotName] = null;
|
17451
|
+
}
|
17452
|
+
}
|
17453
|
+
|
16948
17454
|
return boundTranscludeFn;
|
16949
17455
|
}
|
16950
17456
|
|
@@ -17103,6 +17609,37 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
17103
17609
|
};
|
17104
17610
|
}
|
17105
17611
|
|
17612
|
+
/**
|
17613
|
+
* A function generator that is used to support both eager and lazy compilation
|
17614
|
+
* linking function.
|
17615
|
+
* @param eager
|
17616
|
+
* @param $compileNodes
|
17617
|
+
* @param transcludeFn
|
17618
|
+
* @param maxPriority
|
17619
|
+
* @param ignoreDirective
|
17620
|
+
* @param previousCompileContext
|
17621
|
+
* @returns {Function}
|
17622
|
+
*/
|
17623
|
+
function compilationGenerator(eager, $compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext) {
|
17624
|
+
if (eager) {
|
17625
|
+
return compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext);
|
17626
|
+
}
|
17627
|
+
|
17628
|
+
var compiled;
|
17629
|
+
|
17630
|
+
return function() {
|
17631
|
+
if (!compiled) {
|
17632
|
+
compiled = compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext);
|
17633
|
+
|
17634
|
+
// Null out all of these references in order to make them eligible for garbage collection
|
17635
|
+
// since this is a potentially long lived closure
|
17636
|
+
$compileNodes = transcludeFn = previousCompileContext = null;
|
17637
|
+
}
|
17638
|
+
|
17639
|
+
return compiled.apply(this, arguments);
|
17640
|
+
};
|
17641
|
+
}
|
17642
|
+
|
17106
17643
|
/**
|
17107
17644
|
* Once the directives have been collected, their compile functions are executed. This method
|
17108
17645
|
* is responsible for inlining directive templates as well as terminating the application
|
@@ -17147,6 +17684,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
17147
17684
|
replaceDirective = originalReplaceDirective,
|
17148
17685
|
childTranscludeFn = transcludeFn,
|
17149
17686
|
linkFn,
|
17687
|
+
didScanForMultipleTransclusion = false,
|
17688
|
+
mightHaveMultipleTransclusionError = false,
|
17150
17689
|
directiveValue;
|
17151
17690
|
|
17152
17691
|
// executes all directives on the current element
|
@@ -17189,6 +17728,27 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
17189
17728
|
|
17190
17729
|
directiveName = directive.name;
|
17191
17730
|
|
17731
|
+
// If we encounter a condition that can result in transclusion on the directive,
|
17732
|
+
// then scan ahead in the remaining directives for others that may cause a multiple
|
17733
|
+
// transclusion error to be thrown during the compilation process. If a matching directive
|
17734
|
+
// is found, then we know that when we encounter a transcluded directive, we need to eagerly
|
17735
|
+
// compile the `transclude` function rather than doing it lazily in order to throw
|
17736
|
+
// exceptions at the correct time
|
17737
|
+
if (!didScanForMultipleTransclusion && ((directive.replace && (directive.templateUrl || directive.template))
|
17738
|
+
|| (directive.transclude && !directive.$$tlb))) {
|
17739
|
+
var candidateDirective;
|
17740
|
+
|
17741
|
+
for (var scanningIndex = i + 1; candidateDirective = directives[scanningIndex++];) {
|
17742
|
+
if ((candidateDirective.transclude && !candidateDirective.$$tlb)
|
17743
|
+
|| (candidateDirective.replace && (candidateDirective.templateUrl || candidateDirective.template))) {
|
17744
|
+
mightHaveMultipleTransclusionError = true;
|
17745
|
+
break;
|
17746
|
+
}
|
17747
|
+
}
|
17748
|
+
|
17749
|
+
didScanForMultipleTransclusion = true;
|
17750
|
+
}
|
17751
|
+
|
17192
17752
|
if (!directive.templateUrl && directive.controller) {
|
17193
17753
|
directiveValue = directive.controller;
|
17194
17754
|
controllerDirectives = controllerDirectives || createMap();
|
@@ -17218,7 +17778,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
17218
17778
|
compileNode = $compileNode[0];
|
17219
17779
|
replaceWith(jqCollection, sliceArgs($template), compileNode);
|
17220
17780
|
|
17221
|
-
childTranscludeFn =
|
17781
|
+
childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, terminalPriority,
|
17222
17782
|
replaceDirective && replaceDirective.name, {
|
17223
17783
|
// Don't pass in:
|
17224
17784
|
// - controllerDirectives - otherwise we'll create duplicates controllers
|
@@ -17230,10 +17790,69 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
17230
17790
|
nonTlbTranscludeDirective: nonTlbTranscludeDirective
|
17231
17791
|
});
|
17232
17792
|
} else {
|
17793
|
+
|
17794
|
+
var slots = createMap();
|
17795
|
+
|
17233
17796
|
$template = jqLite(jqLiteClone(compileNode)).contents();
|
17797
|
+
|
17798
|
+
if (isObject(directiveValue)) {
|
17799
|
+
|
17800
|
+
// We have transclusion slots,
|
17801
|
+
// collect them up, compile them and store their transclusion functions
|
17802
|
+
$template = [];
|
17803
|
+
|
17804
|
+
var slotMap = createMap();
|
17805
|
+
var filledSlots = createMap();
|
17806
|
+
|
17807
|
+
// Parse the element selectors
|
17808
|
+
forEach(directiveValue, function(elementSelector, slotName) {
|
17809
|
+
// If an element selector starts with a ? then it is optional
|
17810
|
+
var optional = (elementSelector.charAt(0) === '?');
|
17811
|
+
elementSelector = optional ? elementSelector.substring(1) : elementSelector;
|
17812
|
+
|
17813
|
+
slotMap[elementSelector] = slotName;
|
17814
|
+
|
17815
|
+
// We explicitly assign `null` since this implies that a slot was defined but not filled.
|
17816
|
+
// Later when calling boundTransclusion functions with a slot name we only error if the
|
17817
|
+
// slot is `undefined`
|
17818
|
+
slots[slotName] = null;
|
17819
|
+
|
17820
|
+
// filledSlots contains `true` for all slots that are either optional or have been
|
17821
|
+
// filled. This is used to check that we have not missed any required slots
|
17822
|
+
filledSlots[slotName] = optional;
|
17823
|
+
});
|
17824
|
+
|
17825
|
+
// Add the matching elements into their slot
|
17826
|
+
forEach($compileNode.contents(), function(node) {
|
17827
|
+
var slotName = slotMap[directiveNormalize(nodeName_(node))];
|
17828
|
+
if (slotName) {
|
17829
|
+
filledSlots[slotName] = true;
|
17830
|
+
slots[slotName] = slots[slotName] || [];
|
17831
|
+
slots[slotName].push(node);
|
17832
|
+
} else {
|
17833
|
+
$template.push(node);
|
17834
|
+
}
|
17835
|
+
});
|
17836
|
+
|
17837
|
+
// Check for required slots that were not filled
|
17838
|
+
forEach(filledSlots, function(filled, slotName) {
|
17839
|
+
if (!filled) {
|
17840
|
+
throw $compileMinErr('reqslot', 'Required transclusion slot `{0}` was not filled.', slotName);
|
17841
|
+
}
|
17842
|
+
});
|
17843
|
+
|
17844
|
+
for (var slotName in slots) {
|
17845
|
+
if (slots[slotName]) {
|
17846
|
+
// Only define a transclusion function if the slot was filled
|
17847
|
+
slots[slotName] = compilationGenerator(mightHaveMultipleTransclusionError, slots[slotName], transcludeFn);
|
17848
|
+
}
|
17849
|
+
}
|
17850
|
+
}
|
17851
|
+
|
17234
17852
|
$compileNode.empty(); // clear contents
|
17235
|
-
childTranscludeFn =
|
17853
|
+
childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, undefined,
|
17236
17854
|
undefined, { needsNewScope: directive.$$isolateScope || directive.$$newScope});
|
17855
|
+
childTranscludeFn.$$slots = slots;
|
17237
17856
|
}
|
17238
17857
|
}
|
17239
17858
|
|
@@ -17396,6 +18015,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
17396
18015
|
for (var i = 0, ii = require.length; i < ii; i++) {
|
17397
18016
|
value[i] = getControllers(directiveName, require[i], $element, elementControllers);
|
17398
18017
|
}
|
18018
|
+
} else if (isObject(require)) {
|
18019
|
+
value = {};
|
18020
|
+
forEach(require, function(controller, property) {
|
18021
|
+
value[property] = getControllers(directiveName, controller, $element, elementControllers);
|
18022
|
+
});
|
17399
18023
|
}
|
17400
18024
|
|
17401
18025
|
return value || null;
|
@@ -17433,7 +18057,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
17433
18057
|
}
|
17434
18058
|
|
17435
18059
|
function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
|
17436
|
-
var linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element,
|
18060
|
+
var i, ii, linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element,
|
17437
18061
|
attrs, removeScopeBindingWatches, removeControllerBindingWatches;
|
17438
18062
|
|
17439
18063
|
if (compileNode === linkNode) {
|
@@ -17456,6 +18080,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
17456
18080
|
// is later passed as `parentBoundTranscludeFn` to `publicLinkFn`
|
17457
18081
|
transcludeFn = controllersBoundTransclude;
|
17458
18082
|
transcludeFn.$$boundTransclude = boundTranscludeFn;
|
18083
|
+
// expose the slots on the `$transclude` function
|
18084
|
+
transcludeFn.isSlotFilled = function(slotName) {
|
18085
|
+
return !!boundTranscludeFn.$$slots[slotName];
|
18086
|
+
};
|
17459
18087
|
}
|
17460
18088
|
|
17461
18089
|
if (controllerDirectives) {
|
@@ -17500,6 +18128,21 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
17500
18128
|
}
|
17501
18129
|
}
|
17502
18130
|
|
18131
|
+
// Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy
|
18132
|
+
forEach(controllerDirectives, function(controllerDirective, name) {
|
18133
|
+
var require = controllerDirective.require;
|
18134
|
+
if (controllerDirective.bindToController && !isArray(require) && isObject(require)) {
|
18135
|
+
extend(elementControllers[name].instance, getControllers(name, require, $element, elementControllers));
|
18136
|
+
}
|
18137
|
+
});
|
18138
|
+
|
18139
|
+
// Trigger the `$onInit` method on all controllers that have one
|
18140
|
+
forEach(elementControllers, function(controller) {
|
18141
|
+
if (isFunction(controller.instance.$onInit)) {
|
18142
|
+
controller.instance.$onInit();
|
18143
|
+
}
|
18144
|
+
});
|
18145
|
+
|
17503
18146
|
// PRELINKING
|
17504
18147
|
for (i = 0, ii = preLinkFns.length; i < ii; i++) {
|
17505
18148
|
linkFn = preLinkFns[i];
|
@@ -17535,11 +18178,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
17535
18178
|
|
17536
18179
|
// This is the function that is injected as `$transclude`.
|
17537
18180
|
// Note: all arguments are optional!
|
17538
|
-
function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) {
|
18181
|
+
function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement, slotName) {
|
17539
18182
|
var transcludeControllers;
|
17540
|
-
|
17541
18183
|
// No scope passed in:
|
17542
18184
|
if (!isScope(scope)) {
|
18185
|
+
slotName = futureParentElement;
|
17543
18186
|
futureParentElement = cloneAttachFn;
|
17544
18187
|
cloneAttachFn = scope;
|
17545
18188
|
scope = undefined;
|
@@ -17551,7 +18194,23 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
17551
18194
|
if (!futureParentElement) {
|
17552
18195
|
futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;
|
17553
18196
|
}
|
17554
|
-
|
18197
|
+
if (slotName) {
|
18198
|
+
// slotTranscludeFn can be one of three things:
|
18199
|
+
// * a transclude function - a filled slot
|
18200
|
+
// * `null` - an optional slot that was not filled
|
18201
|
+
// * `undefined` - a slot that was not declared (i.e. invalid)
|
18202
|
+
var slotTranscludeFn = boundTranscludeFn.$$slots[slotName];
|
18203
|
+
if (slotTranscludeFn) {
|
18204
|
+
return slotTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
|
18205
|
+
} else if (isUndefined(slotTranscludeFn)) {
|
18206
|
+
throw $compileMinErr('noslot',
|
18207
|
+
'No parent directive that requires a transclusion with slot name "{0}". ' +
|
18208
|
+
'Element: {1}',
|
18209
|
+
slotName, startingTag($element));
|
18210
|
+
}
|
18211
|
+
} else {
|
18212
|
+
return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
|
18213
|
+
}
|
17555
18214
|
}
|
17556
18215
|
}
|
17557
18216
|
}
|
@@ -17983,9 +18642,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
17983
18642
|
parent.replaceChild(newNode, firstElementToRemove);
|
17984
18643
|
}
|
17985
18644
|
|
17986
|
-
//
|
18645
|
+
// Append all the `elementsToRemove` to a fragment. This will...
|
18646
|
+
// - remove them from the DOM
|
18647
|
+
// - allow them to still be traversed with .nextSibling
|
18648
|
+
// - allow a single fragment.qSA to fetch all elements being removed
|
17987
18649
|
var fragment = document.createDocumentFragment();
|
17988
|
-
|
18650
|
+
for (i = 0; i < removeCount; i++) {
|
18651
|
+
fragment.appendChild(elementsToRemove[i]);
|
18652
|
+
}
|
17989
18653
|
|
17990
18654
|
if (jqLite.hasData(firstElementToRemove)) {
|
17991
18655
|
// Copy over user data (that includes Angular's $scope etc.). Don't copy private
|
@@ -17993,31 +18657,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
17993
18657
|
// event listeners (which is the main use of private data) wouldn't work anyway.
|
17994
18658
|
jqLite.data(newNode, jqLite.data(firstElementToRemove));
|
17995
18659
|
|
17996
|
-
// Remove
|
17997
|
-
|
17998
|
-
// for the new node. Instead, remove the data "manually".
|
17999
|
-
if (!jQuery) {
|
18000
|
-
delete jqLite.cache[firstElementToRemove[jqLite.expando]];
|
18001
|
-
} else {
|
18002
|
-
// jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after
|
18003
|
-
// the replaced element. The cleanData version monkey-patched by Angular would cause
|
18004
|
-
// the scope to be trashed and we do need the very same scope to work with the new
|
18005
|
-
// element. However, we cannot just cache the non-patched version and use it here as
|
18006
|
-
// that would break if another library patches the method after Angular does (one
|
18007
|
-
// example is jQuery UI). Instead, set a flag indicating scope destroying should be
|
18008
|
-
// skipped this one time.
|
18009
|
-
skipDestroyOnNextJQueryCleanData = true;
|
18010
|
-
jQuery.cleanData([firstElementToRemove]);
|
18011
|
-
}
|
18660
|
+
// Remove $destroy event listeners from `firstElementToRemove`
|
18661
|
+
jqLite(firstElementToRemove).off('$destroy');
|
18012
18662
|
}
|
18013
18663
|
|
18014
|
-
|
18015
|
-
|
18016
|
-
|
18017
|
-
fragment.appendChild(element);
|
18018
|
-
delete elementsToRemove[k];
|
18019
|
-
}
|
18664
|
+
// Cleanup any data/listeners on the elements and children.
|
18665
|
+
// This includes invoking the $destroy event on any elements with listeners.
|
18666
|
+
jqLite.cleanData(fragment.querySelectorAll('*'));
|
18020
18667
|
|
18668
|
+
// Update the jqLite collection to only contain the `newNode`
|
18669
|
+
for (i = 1; i < removeCount; i++) {
|
18670
|
+
delete elementsToRemove[i];
|
18671
|
+
}
|
18021
18672
|
elementsToRemove[0] = newNode;
|
18022
18673
|
elementsToRemove.length = 1;
|
18023
18674
|
}
|
@@ -18046,7 +18697,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
18046
18697
|
optional = definition.optional,
|
18047
18698
|
mode = definition.mode, // @, =, or &
|
18048
18699
|
lastValue,
|
18049
|
-
parentGet, parentSet, compare;
|
18700
|
+
parentGet, parentSet, compare, removeWatch;
|
18050
18701
|
|
18051
18702
|
switch (mode) {
|
18052
18703
|
|
@@ -18060,10 +18711,15 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
18060
18711
|
}
|
18061
18712
|
});
|
18062
18713
|
attrs.$$observers[attrName].$$scope = scope;
|
18063
|
-
|
18714
|
+
lastValue = attrs[attrName];
|
18715
|
+
if (isString(lastValue)) {
|
18064
18716
|
// If the attribute has been provided then we trigger an interpolation to ensure
|
18065
18717
|
// the value is there for use in the link fn
|
18066
|
-
destination[scopeName] = $interpolate(
|
18718
|
+
destination[scopeName] = $interpolate(lastValue)(scope);
|
18719
|
+
} else if (isBoolean(lastValue)) {
|
18720
|
+
// If the attributes is one of the BOOLEAN_ATTR then Angular will have converted
|
18721
|
+
// the value to boolean rather than a string, so we special case this situation
|
18722
|
+
destination[scopeName] = lastValue;
|
18067
18723
|
}
|
18068
18724
|
break;
|
18069
18725
|
|
@@ -18084,8 +18740,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
18084
18740
|
// reset the change, or we will throw this exception on every $digest
|
18085
18741
|
lastValue = destination[scopeName] = parentGet(scope);
|
18086
18742
|
throw $compileMinErr('nonassign',
|
18087
|
-
"Expression '{0}' used with directive '{
|
18088
|
-
attrs[attrName], directive.name);
|
18743
|
+
"Expression '{0}' in attribute '{1}' used with directive '{2}' is non-assignable!",
|
18744
|
+
attrs[attrName], attrName, directive.name);
|
18089
18745
|
};
|
18090
18746
|
lastValue = destination[scopeName] = parentGet(scope);
|
18091
18747
|
var parentValueWatch = function parentValueWatch(parentValue) {
|
@@ -18102,7 +18758,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
18102
18758
|
return lastValue = parentValue;
|
18103
18759
|
};
|
18104
18760
|
parentValueWatch.$stateful = true;
|
18105
|
-
var removeWatch;
|
18106
18761
|
if (definition.collection) {
|
18107
18762
|
removeWatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
|
18108
18763
|
} else {
|
@@ -18111,6 +18766,24 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
18111
18766
|
removeWatchCollection.push(removeWatch);
|
18112
18767
|
break;
|
18113
18768
|
|
18769
|
+
case '<':
|
18770
|
+
if (!hasOwnProperty.call(attrs, attrName)) {
|
18771
|
+
if (optional) break;
|
18772
|
+
attrs[attrName] = void 0;
|
18773
|
+
}
|
18774
|
+
if (optional && !attrs[attrName]) break;
|
18775
|
+
|
18776
|
+
parentGet = $parse(attrs[attrName]);
|
18777
|
+
|
18778
|
+
destination[scopeName] = parentGet(scope);
|
18779
|
+
|
18780
|
+
removeWatch = scope.$watch(parentGet, function parentValueWatchAction(newParentValue) {
|
18781
|
+
destination[scopeName] = newParentValue;
|
18782
|
+
}, parentGet.literal);
|
18783
|
+
|
18784
|
+
removeWatchCollection.push(removeWatch);
|
18785
|
+
break;
|
18786
|
+
|
18114
18787
|
case '&':
|
18115
18788
|
// Don't assign Object.prototype method to scope
|
18116
18789
|
parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop;
|
@@ -18239,7 +18912,7 @@ function removeComments(jqNodes) {
|
|
18239
18912
|
var $controllerMinErr = minErr('$controller');
|
18240
18913
|
|
18241
18914
|
|
18242
|
-
var CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
|
18915
|
+
var CNTRL_REG = /^(\S+)(\s+as\s+([\w$]+))?$/;
|
18243
18916
|
function identifierForController(controller, ident) {
|
18244
18917
|
if (ident && isString(ident)) return ident;
|
18245
18918
|
if (isString(controller)) {
|
@@ -19030,7 +19703,7 @@ function $HttpProvider() {
|
|
19030
19703
|
*
|
19031
19704
|
* ```
|
19032
19705
|
* module.run(function($http) {
|
19033
|
-
* $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'
|
19706
|
+
* $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w';
|
19034
19707
|
* });
|
19035
19708
|
* ```
|
19036
19709
|
*
|
@@ -19258,13 +19931,13 @@ function $HttpProvider() {
|
|
19258
19931
|
*
|
19259
19932
|
* ### Cross Site Request Forgery (XSRF) Protection
|
19260
19933
|
*
|
19261
|
-
* [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is
|
19262
|
-
*
|
19263
|
-
* to counter XSRF. When performing XHR requests, the
|
19264
|
-
* (by default, `XSRF-TOKEN`) and sets it as an HTTP
|
19265
|
-
* JavaScript that runs on your domain could read the
|
19266
|
-
* the XHR came from JavaScript running on your domain.
|
19267
|
-
* cross-domain requests.
|
19934
|
+
* [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by
|
19935
|
+
* which the attacker can trick an authenticated user into unknowingly executing actions on your
|
19936
|
+
* website. Angular provides a mechanism to counter XSRF. When performing XHR requests, the
|
19937
|
+
* $http service reads a token from a cookie (by default, `XSRF-TOKEN`) and sets it as an HTTP
|
19938
|
+
* header (`X-XSRF-TOKEN`). Since only JavaScript that runs on your domain could read the
|
19939
|
+
* cookie, your server can be assured that the XHR came from JavaScript running on your domain.
|
19940
|
+
* The header will not be set for cross-domain requests.
|
19268
19941
|
*
|
19269
19942
|
* To take advantage of this, your server needs to set a token in a JavaScript readable session
|
19270
19943
|
* cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
|
@@ -19423,10 +20096,14 @@ function $HttpProvider() {
|
|
19423
20096
|
*/
|
19424
20097
|
function $http(requestConfig) {
|
19425
20098
|
|
19426
|
-
if (!
|
20099
|
+
if (!isObject(requestConfig)) {
|
19427
20100
|
throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig);
|
19428
20101
|
}
|
19429
20102
|
|
20103
|
+
if (!isString(requestConfig.url)) {
|
20104
|
+
throw minErr('$http')('badreq', 'Http request configuration url must be a string. Received: {0}', requestConfig.url);
|
20105
|
+
}
|
20106
|
+
|
19430
20107
|
var config = extend({
|
19431
20108
|
method: 'get',
|
19432
20109
|
transformRequest: defaults.transformRequest,
|
@@ -19539,7 +20216,7 @@ function $HttpProvider() {
|
|
19539
20216
|
|
19540
20217
|
defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
|
19541
20218
|
|
19542
|
-
// using for-in instead of forEach to avoid
|
20219
|
+
// using for-in instead of forEach to avoid unnecessary iteration after header has been found
|
19543
20220
|
defaultHeadersIteration:
|
19544
20221
|
for (defHeaderName in defHeaders) {
|
19545
20222
|
lowercaseDefHeaderName = lowercase(defHeaderName);
|
@@ -20038,8 +20715,16 @@ $interpolateMinErr.interr = function(text, err) {
|
|
20038
20715
|
*
|
20039
20716
|
* Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
|
20040
20717
|
*
|
20718
|
+
* <div class="alert alert-danger">
|
20719
|
+
* This feature is sometimes used to mix different markup languages, e.g. to wrap an Angular
|
20720
|
+
* template within a Python Jinja template (or any other template language). Mixing templating
|
20721
|
+
* languages is **very dangerous**. The embedding template language will not safely escape Angular
|
20722
|
+
* expressions, so any user-controlled values in the template will cause Cross Site Scripting (XSS)
|
20723
|
+
* security bugs!
|
20724
|
+
* </div>
|
20725
|
+
*
|
20041
20726
|
* @example
|
20042
|
-
<example module="customInterpolationApp">
|
20727
|
+
<example name="custom-interpolation-markup" module="customInterpolationApp">
|
20043
20728
|
<file name="index.html">
|
20044
20729
|
<script>
|
20045
20730
|
var customInterpolationApp = angular.module('customInterpolationApp', []);
|
@@ -20054,7 +20739,7 @@ $interpolateMinErr.interr = function(text, err) {
|
|
20054
20739
|
this.label = "This binding is brought you by // interpolation symbols.";
|
20055
20740
|
});
|
20056
20741
|
</script>
|
20057
|
-
<div ng-
|
20742
|
+
<div ng-controller="DemoController as demo">
|
20058
20743
|
//demo.label//
|
20059
20744
|
</div>
|
20060
20745
|
</file>
|
@@ -20138,6 +20823,15 @@ function $InterpolateProvider() {
|
|
20138
20823
|
return value;
|
20139
20824
|
}
|
20140
20825
|
|
20826
|
+
//TODO: this is the same as the constantWatchDelegate in parse.js
|
20827
|
+
function constantWatchDelegate(scope, listener, objectEquality, constantInterp) {
|
20828
|
+
var unwatch;
|
20829
|
+
return unwatch = scope.$watch(function constantInterpolateWatch(scope) {
|
20830
|
+
unwatch();
|
20831
|
+
return constantInterp(scope);
|
20832
|
+
}, listener, objectEquality);
|
20833
|
+
}
|
20834
|
+
|
20141
20835
|
/**
|
20142
20836
|
* @ngdoc service
|
20143
20837
|
* @name $interpolate
|
@@ -20233,6 +20927,19 @@ function $InterpolateProvider() {
|
|
20233
20927
|
* - `context`: evaluation context for all expressions embedded in the interpolated text
|
20234
20928
|
*/
|
20235
20929
|
function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {
|
20930
|
+
// Provide a quick exit and simplified result function for text with no interpolation
|
20931
|
+
if (!text.length || text.indexOf(startSymbol) === -1) {
|
20932
|
+
var constantInterp;
|
20933
|
+
if (!mustHaveExpression) {
|
20934
|
+
var unescapedText = unescapeText(text);
|
20935
|
+
constantInterp = valueFn(unescapedText);
|
20936
|
+
constantInterp.exp = text;
|
20937
|
+
constantInterp.expressions = [];
|
20938
|
+
constantInterp.$$watchDelegate = constantWatchDelegate;
|
20939
|
+
}
|
20940
|
+
return constantInterp;
|
20941
|
+
}
|
20942
|
+
|
20236
20943
|
allOrNothing = !!allOrNothing;
|
20237
20944
|
var startIndex,
|
20238
20945
|
endIndex,
|
@@ -20369,8 +21076,8 @@ function $InterpolateProvider() {
|
|
20369
21076
|
}
|
20370
21077
|
|
20371
21078
|
function $IntervalProvider() {
|
20372
|
-
this.$get = ['$rootScope', '$window', '$q', '$$q',
|
20373
|
-
function($rootScope, $window, $q, $$q) {
|
21079
|
+
this.$get = ['$rootScope', '$window', '$q', '$$q', '$browser',
|
21080
|
+
function($rootScope, $window, $q, $$q, $browser) {
|
20374
21081
|
var intervals = {};
|
20375
21082
|
|
20376
21083
|
|
@@ -20511,11 +21218,12 @@ function $IntervalProvider() {
|
|
20511
21218
|
|
20512
21219
|
count = isDefined(count) ? count : 0;
|
20513
21220
|
|
20514
|
-
promise.then(null, null, (!hasParams) ? fn : function() {
|
20515
|
-
fn.apply(null, args);
|
20516
|
-
});
|
20517
|
-
|
20518
21221
|
promise.$$intervalId = setInterval(function tick() {
|
21222
|
+
if (skipApply) {
|
21223
|
+
$browser.defer(callback);
|
21224
|
+
} else {
|
21225
|
+
$rootScope.$evalAsync(callback);
|
21226
|
+
}
|
20519
21227
|
deferred.notify(iteration++);
|
20520
21228
|
|
20521
21229
|
if (count > 0 && iteration >= count) {
|
@@ -20531,6 +21239,14 @@ function $IntervalProvider() {
|
|
20531
21239
|
intervals[promise.$$intervalId] = deferred;
|
20532
21240
|
|
20533
21241
|
return promise;
|
21242
|
+
|
21243
|
+
function callback() {
|
21244
|
+
if (!hasParams) {
|
21245
|
+
fn(iteration);
|
21246
|
+
} else {
|
21247
|
+
fn.apply(null, args);
|
21248
|
+
}
|
21249
|
+
}
|
20534
21250
|
}
|
20535
21251
|
|
20536
21252
|
|
@@ -21770,23 +22486,22 @@ function ensureSafeMemberName(name, fullExpression) {
|
|
21770
22486
|
return name;
|
21771
22487
|
}
|
21772
22488
|
|
21773
|
-
function getStringValue(name
|
21774
|
-
// From the JavaScript docs:
|
22489
|
+
function getStringValue(name) {
|
21775
22490
|
// Property names must be strings. This means that non-string objects cannot be used
|
21776
22491
|
// as keys in an object. Any non-string object, including a number, is typecasted
|
21777
22492
|
// into a string via the toString method.
|
22493
|
+
// -- MDN, https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Property_accessors#Property_names
|
21778
22494
|
//
|
21779
|
-
// So, to ensure that we are checking the same `name` that JavaScript would use,
|
21780
|
-
//
|
21781
|
-
//
|
21782
|
-
//
|
21783
|
-
|
21784
|
-
|
21785
|
-
|
21786
|
-
|
21787
|
-
|
21788
|
-
|
21789
|
-
return name;
|
22495
|
+
// So, to ensure that we are checking the same `name` that JavaScript would use, we cast it
|
22496
|
+
// to a string. It's not always possible. If `name` is an object and its `toString` method is
|
22497
|
+
// 'broken' (doesn't return a string, isn't a function, etc.), an error will be thrown:
|
22498
|
+
//
|
22499
|
+
// TypeError: Cannot convert object to primitive value
|
22500
|
+
//
|
22501
|
+
// For performance reasons, we don't catch this error here and allow it to propagate up the call
|
22502
|
+
// stack. Note that you'll get the same error in JavaScript if you try to access a property using
|
22503
|
+
// such a 'broken' object as a key.
|
22504
|
+
return name + '';
|
21790
22505
|
}
|
21791
22506
|
|
21792
22507
|
function ensureSafeObject(obj, fullExpression) {
|
@@ -22047,6 +22762,7 @@ AST.ArrayExpression = 'ArrayExpression';
|
|
22047
22762
|
AST.Property = 'Property';
|
22048
22763
|
AST.ObjectExpression = 'ObjectExpression';
|
22049
22764
|
AST.ThisExpression = 'ThisExpression';
|
22765
|
+
AST.LocalsExpression = 'LocalsExpression';
|
22050
22766
|
|
22051
22767
|
// Internal use only
|
22052
22768
|
AST.NGValueParameter = 'NGValueParameter';
|
@@ -22347,7 +23063,8 @@ AST.prototype = {
|
|
22347
23063
|
'false': { type: AST.Literal, value: false },
|
22348
23064
|
'null': { type: AST.Literal, value: null },
|
22349
23065
|
'undefined': {type: AST.Literal, value: undefined },
|
22350
|
-
'this': {type: AST.ThisExpression }
|
23066
|
+
'this': {type: AST.ThisExpression },
|
23067
|
+
'$locals': {type: AST.LocalsExpression }
|
22351
23068
|
}
|
22352
23069
|
};
|
22353
23070
|
|
@@ -22467,6 +23184,10 @@ function findConstantAndWatchExpressions(ast, $filter) {
|
|
22467
23184
|
ast.constant = false;
|
22468
23185
|
ast.toWatch = [];
|
22469
23186
|
break;
|
23187
|
+
case AST.LocalsExpression:
|
23188
|
+
ast.constant = false;
|
23189
|
+
ast.toWatch = [];
|
23190
|
+
break;
|
22470
23191
|
}
|
22471
23192
|
}
|
22472
23193
|
|
@@ -22710,6 +23431,9 @@ ASTCompiler.prototype = {
|
|
22710
23431
|
intoId = intoId || this.nextId();
|
22711
23432
|
self.recurse(ast.object, left, undefined, function() {
|
22712
23433
|
self.if_(self.notNull(left), function() {
|
23434
|
+
if (create && create !== 1) {
|
23435
|
+
self.addEnsureSafeAssignContext(left);
|
23436
|
+
}
|
22713
23437
|
if (ast.computed) {
|
22714
23438
|
right = self.nextId();
|
22715
23439
|
self.recurse(ast.property, right);
|
@@ -22791,7 +23515,7 @@ ASTCompiler.prototype = {
|
|
22791
23515
|
right = this.nextId();
|
22792
23516
|
left = {};
|
22793
23517
|
if (!isAssignable(ast.left)) {
|
22794
|
-
throw $parseMinErr('lval', 'Trying to
|
23518
|
+
throw $parseMinErr('lval', 'Trying to assign a value to a non l-value');
|
22795
23519
|
}
|
22796
23520
|
this.recurse(ast.left, undefined, left, function() {
|
22797
23521
|
self.if_(self.notNull(left.context), function() {
|
@@ -22833,6 +23557,10 @@ ASTCompiler.prototype = {
|
|
22833
23557
|
this.assign(intoId, 's');
|
22834
23558
|
recursionFn('s');
|
22835
23559
|
break;
|
23560
|
+
case AST.LocalsExpression:
|
23561
|
+
this.assign(intoId, 'l');
|
23562
|
+
recursionFn('l');
|
23563
|
+
break;
|
22836
23564
|
case AST.NGValueParameter:
|
22837
23565
|
this.assign(intoId, 'v');
|
22838
23566
|
recursionFn('v');
|
@@ -22940,7 +23668,7 @@ ASTCompiler.prototype = {
|
|
22940
23668
|
},
|
22941
23669
|
|
22942
23670
|
getStringValue: function(item) {
|
22943
|
-
this.assign(item, 'getStringValue(' + item + '
|
23671
|
+
this.assign(item, 'getStringValue(' + item + ')');
|
22944
23672
|
},
|
22945
23673
|
|
22946
23674
|
ensureSafeAssignContext: function(item) {
|
@@ -23160,6 +23888,10 @@ ASTInterpreter.prototype = {
|
|
23160
23888
|
return function(scope) {
|
23161
23889
|
return context ? {value: scope} : scope;
|
23162
23890
|
};
|
23891
|
+
case AST.LocalsExpression:
|
23892
|
+
return function(scope, locals) {
|
23893
|
+
return context ? {value: locals} : locals;
|
23894
|
+
};
|
23163
23895
|
case AST.NGValueParameter:
|
23164
23896
|
return function(scope, locals, assign, inputs) {
|
23165
23897
|
return context ? {value: assign} : assign;
|
@@ -23324,8 +24056,11 @@ ASTInterpreter.prototype = {
|
|
23324
24056
|
rhs = right(scope, locals, assign, inputs);
|
23325
24057
|
rhs = getStringValue(rhs);
|
23326
24058
|
ensureSafeMemberName(rhs, expression);
|
23327
|
-
if (create && create !== 1
|
23328
|
-
lhs
|
24059
|
+
if (create && create !== 1) {
|
24060
|
+
ensureSafeAssignContext(lhs);
|
24061
|
+
if (lhs && !(lhs[rhs])) {
|
24062
|
+
lhs[rhs] = {};
|
24063
|
+
}
|
23329
24064
|
}
|
23330
24065
|
value = lhs[rhs];
|
23331
24066
|
ensureSafeObject(value, expression);
|
@@ -23340,8 +24075,11 @@ ASTInterpreter.prototype = {
|
|
23340
24075
|
nonComputedMember: function(left, right, expensiveChecks, context, create, expression) {
|
23341
24076
|
return function(scope, locals, assign, inputs) {
|
23342
24077
|
var lhs = left(scope, locals, assign, inputs);
|
23343
|
-
if (create && create !== 1
|
23344
|
-
lhs
|
24078
|
+
if (create && create !== 1) {
|
24079
|
+
ensureSafeAssignContext(lhs);
|
24080
|
+
if (lhs && !(lhs[right])) {
|
24081
|
+
lhs[right] = {};
|
24082
|
+
}
|
23345
24083
|
}
|
23346
24084
|
var value = lhs != null ? lhs[right] : undefined;
|
23347
24085
|
if (expensiveChecks || isPossiblyDangerousMemberName(right)) {
|
@@ -23382,9 +24120,6 @@ Parser.prototype = {
|
|
23382
24120
|
}
|
23383
24121
|
};
|
23384
24122
|
|
23385
|
-
var getterFnCacheDefault = createMap();
|
23386
|
-
var getterFnCacheExpensive = createMap();
|
23387
|
-
|
23388
24123
|
function isPossiblyDangerousMemberName(name) {
|
23389
24124
|
return name == 'constructor';
|
23390
24125
|
}
|
@@ -23460,10 +24195,19 @@ function $ParseProvider() {
|
|
23460
24195
|
csp: noUnsafeEval,
|
23461
24196
|
expensiveChecks: true
|
23462
24197
|
};
|
24198
|
+
var runningChecksEnabled = false;
|
24199
|
+
|
24200
|
+
$parse.$$runningExpensiveChecks = function() {
|
24201
|
+
return runningChecksEnabled;
|
24202
|
+
};
|
24203
|
+
|
24204
|
+
return $parse;
|
23463
24205
|
|
23464
|
-
|
24206
|
+
function $parse(exp, interceptorFn, expensiveChecks) {
|
23465
24207
|
var parsedExpression, oneTime, cacheKey;
|
23466
24208
|
|
24209
|
+
expensiveChecks = expensiveChecks || runningChecksEnabled;
|
24210
|
+
|
23467
24211
|
switch (typeof exp) {
|
23468
24212
|
case 'string':
|
23469
24213
|
exp = exp.trim();
|
@@ -23489,6 +24233,9 @@ function $ParseProvider() {
|
|
23489
24233
|
} else if (parsedExpression.inputs) {
|
23490
24234
|
parsedExpression.$$watchDelegate = inputsWatchDelegate;
|
23491
24235
|
}
|
24236
|
+
if (expensiveChecks) {
|
24237
|
+
parsedExpression = expensiveChecksInterceptor(parsedExpression);
|
24238
|
+
}
|
23492
24239
|
cache[cacheKey] = parsedExpression;
|
23493
24240
|
}
|
23494
24241
|
return addInterceptor(parsedExpression, interceptorFn);
|
@@ -23497,9 +24244,33 @@ function $ParseProvider() {
|
|
23497
24244
|
return addInterceptor(exp, interceptorFn);
|
23498
24245
|
|
23499
24246
|
default:
|
23500
|
-
return noop;
|
24247
|
+
return addInterceptor(noop, interceptorFn);
|
23501
24248
|
}
|
23502
|
-
}
|
24249
|
+
}
|
24250
|
+
|
24251
|
+
function expensiveChecksInterceptor(fn) {
|
24252
|
+
if (!fn) return fn;
|
24253
|
+
expensiveCheckFn.$$watchDelegate = fn.$$watchDelegate;
|
24254
|
+
expensiveCheckFn.assign = expensiveChecksInterceptor(fn.assign);
|
24255
|
+
expensiveCheckFn.constant = fn.constant;
|
24256
|
+
expensiveCheckFn.literal = fn.literal;
|
24257
|
+
for (var i = 0; fn.inputs && i < fn.inputs.length; ++i) {
|
24258
|
+
fn.inputs[i] = expensiveChecksInterceptor(fn.inputs[i]);
|
24259
|
+
}
|
24260
|
+
expensiveCheckFn.inputs = fn.inputs;
|
24261
|
+
|
24262
|
+
return expensiveCheckFn;
|
24263
|
+
|
24264
|
+
function expensiveCheckFn(scope, locals, assign, inputs) {
|
24265
|
+
var expensiveCheckOldValue = runningChecksEnabled;
|
24266
|
+
runningChecksEnabled = true;
|
24267
|
+
try {
|
24268
|
+
return fn(scope, locals, assign, inputs);
|
24269
|
+
} finally {
|
24270
|
+
runningChecksEnabled = expensiveCheckOldValue;
|
24271
|
+
}
|
24272
|
+
}
|
24273
|
+
}
|
23503
24274
|
|
23504
24275
|
function expressionInputDirtyCheck(newValue, oldValueOfValue) {
|
23505
24276
|
|
@@ -23616,13 +24387,9 @@ function $ParseProvider() {
|
|
23616
24387
|
function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {
|
23617
24388
|
var unwatch;
|
23618
24389
|
return unwatch = scope.$watch(function constantWatch(scope) {
|
23619
|
-
return parsedExpression(scope);
|
23620
|
-
}, function constantListener(value, old, scope) {
|
23621
|
-
if (isFunction(listener)) {
|
23622
|
-
listener.apply(this, arguments);
|
23623
|
-
}
|
23624
24390
|
unwatch();
|
23625
|
-
|
24391
|
+
return parsedExpression(scope);
|
24392
|
+
}, listener, objectEquality);
|
23626
24393
|
}
|
23627
24394
|
|
23628
24395
|
function addInterceptor(parsedExpression, interceptorFn) {
|
@@ -23715,7 +24482,7 @@ function $ParseProvider() {
|
|
23715
24482
|
*
|
23716
24483
|
* Note: progress/notify callbacks are not currently supported via the ES6-style interface.
|
23717
24484
|
*
|
23718
|
-
* Note: unlike ES6
|
24485
|
+
* Note: unlike ES6 behavior, an exception thrown in the constructor function will NOT implicitly reject the promise.
|
23719
24486
|
*
|
23720
24487
|
* However, the more traditional CommonJS-style usage is still available, and documented below.
|
23721
24488
|
*
|
@@ -23905,18 +24672,6 @@ function $$QProvider() {
|
|
23905
24672
|
*/
|
23906
24673
|
function qFactory(nextTick, exceptionHandler) {
|
23907
24674
|
var $qMinErr = minErr('$q', TypeError);
|
23908
|
-
function callOnce(self, resolveFn, rejectFn) {
|
23909
|
-
var called = false;
|
23910
|
-
function wrap(fn) {
|
23911
|
-
return function(value) {
|
23912
|
-
if (called) return;
|
23913
|
-
called = true;
|
23914
|
-
fn.call(self, value);
|
23915
|
-
};
|
23916
|
-
}
|
23917
|
-
|
23918
|
-
return [wrap(resolveFn), wrap(rejectFn)];
|
23919
|
-
}
|
23920
24675
|
|
23921
24676
|
/**
|
23922
24677
|
* @ngdoc method
|
@@ -23929,7 +24684,12 @@ function qFactory(nextTick, exceptionHandler) {
|
|
23929
24684
|
* @returns {Deferred} Returns a new instance of deferred.
|
23930
24685
|
*/
|
23931
24686
|
var defer = function() {
|
23932
|
-
|
24687
|
+
var d = new Deferred();
|
24688
|
+
//Necessary to support unbound execution :/
|
24689
|
+
d.resolve = simpleBind(d, d.resolve);
|
24690
|
+
d.reject = simpleBind(d, d.reject);
|
24691
|
+
d.notify = simpleBind(d, d.notify);
|
24692
|
+
return d;
|
23933
24693
|
};
|
23934
24694
|
|
23935
24695
|
function Promise() {
|
@@ -24002,10 +24762,6 @@ function qFactory(nextTick, exceptionHandler) {
|
|
24002
24762
|
|
24003
24763
|
function Deferred() {
|
24004
24764
|
this.promise = new Promise();
|
24005
|
-
//Necessary to support unbound execution :/
|
24006
|
-
this.resolve = simpleBind(this, this.resolve);
|
24007
|
-
this.reject = simpleBind(this, this.reject);
|
24008
|
-
this.notify = simpleBind(this, this.notify);
|
24009
24765
|
}
|
24010
24766
|
|
24011
24767
|
extend(Deferred.prototype, {
|
@@ -24023,23 +24779,34 @@ function qFactory(nextTick, exceptionHandler) {
|
|
24023
24779
|
},
|
24024
24780
|
|
24025
24781
|
$$resolve: function(val) {
|
24026
|
-
var then
|
24027
|
-
|
24028
|
-
|
24782
|
+
var then;
|
24783
|
+
var that = this;
|
24784
|
+
var done = false;
|
24029
24785
|
try {
|
24030
24786
|
if ((isObject(val) || isFunction(val))) then = val && val.then;
|
24031
24787
|
if (isFunction(then)) {
|
24032
24788
|
this.promise.$$state.status = -1;
|
24033
|
-
then.call(val,
|
24789
|
+
then.call(val, resolvePromise, rejectPromise, simpleBind(this, this.notify));
|
24034
24790
|
} else {
|
24035
24791
|
this.promise.$$state.value = val;
|
24036
24792
|
this.promise.$$state.status = 1;
|
24037
24793
|
scheduleProcessQueue(this.promise.$$state);
|
24038
24794
|
}
|
24039
24795
|
} catch (e) {
|
24040
|
-
|
24796
|
+
rejectPromise(e);
|
24041
24797
|
exceptionHandler(e);
|
24042
24798
|
}
|
24799
|
+
|
24800
|
+
function resolvePromise(val) {
|
24801
|
+
if (done) return;
|
24802
|
+
done = true;
|
24803
|
+
that.$$resolve(val);
|
24804
|
+
}
|
24805
|
+
function rejectPromise(val) {
|
24806
|
+
if (done) return;
|
24807
|
+
done = true;
|
24808
|
+
that.$$reject(val);
|
24809
|
+
}
|
24043
24810
|
},
|
24044
24811
|
|
24045
24812
|
reject: function(reason) {
|
@@ -24228,11 +24995,6 @@ function qFactory(nextTick, exceptionHandler) {
|
|
24228
24995
|
throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver);
|
24229
24996
|
}
|
24230
24997
|
|
24231
|
-
if (!(this instanceof Q)) {
|
24232
|
-
// More useful when $Q is the Promise itself.
|
24233
|
-
return new Q(resolver);
|
24234
|
-
}
|
24235
|
-
|
24236
24998
|
var deferred = new Deferred();
|
24237
24999
|
|
24238
25000
|
function resolveFn(value) {
|
@@ -24248,6 +25010,10 @@ function qFactory(nextTick, exceptionHandler) {
|
|
24248
25010
|
return deferred.promise;
|
24249
25011
|
};
|
24250
25012
|
|
25013
|
+
// Let's make the instanceof operator work for promises, so that
|
25014
|
+
// `new $q(fn) instanceof $q` would evaluate to true.
|
25015
|
+
$Q.prototype = Promise.prototype;
|
25016
|
+
|
24251
25017
|
$Q.defer = defer;
|
24252
25018
|
$Q.reject = reject;
|
24253
25019
|
$Q.when = when;
|
@@ -24381,8 +25147,8 @@ function $RootScopeProvider() {
|
|
24381
25147
|
return ChildScope;
|
24382
25148
|
}
|
24383
25149
|
|
24384
|
-
this.$get = ['$
|
24385
|
-
function($
|
25150
|
+
this.$get = ['$exceptionHandler', '$parse', '$browser',
|
25151
|
+
function($exceptionHandler, $parse, $browser) {
|
24386
25152
|
|
24387
25153
|
function destroyChildScope($event) {
|
24388
25154
|
$event.currentScope.$$destroyed = true;
|
@@ -24666,7 +25432,7 @@ function $RootScopeProvider() {
|
|
24666
25432
|
* - `newVal` contains the current value of the `watchExpression`
|
24667
25433
|
* - `oldVal` contains the previous value of the `watchExpression`
|
24668
25434
|
* - `scope` refers to the current scope
|
24669
|
-
* @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of
|
25435
|
+
* @param {boolean=} [objectEquality=false] Compare for object equality using {@link angular.equals} instead of
|
24670
25436
|
* comparing for reference equality.
|
24671
25437
|
* @returns {function()} Returns a deregistration function for this listener.
|
24672
25438
|
*/
|
@@ -25031,7 +25797,7 @@ function $RootScopeProvider() {
|
|
25031
25797
|
*
|
25032
25798
|
*/
|
25033
25799
|
$digest: function() {
|
25034
|
-
var watch, value, last,
|
25800
|
+
var watch, value, last, fn, get,
|
25035
25801
|
watchers,
|
25036
25802
|
length,
|
25037
25803
|
dirty, ttl = TTL,
|
@@ -25077,7 +25843,8 @@ function $RootScopeProvider() {
|
|
25077
25843
|
// Most common watches are on primitives, in which case we can short
|
25078
25844
|
// circuit it with === operator, only when === fails do we use .equals
|
25079
25845
|
if (watch) {
|
25080
|
-
|
25846
|
+
get = watch.get;
|
25847
|
+
if ((value = get(current)) !== (last = watch.last) &&
|
25081
25848
|
!(watch.eq
|
25082
25849
|
? equals(value, last)
|
25083
25850
|
: (typeof value === 'number' && typeof last === 'number'
|
@@ -25085,7 +25852,8 @@ function $RootScopeProvider() {
|
|
25085
25852
|
dirty = true;
|
25086
25853
|
lastDirtyWatch = watch;
|
25087
25854
|
watch.last = watch.eq ? copy(value, null) : value;
|
25088
|
-
watch.fn
|
25855
|
+
fn = watch.fn;
|
25856
|
+
fn(value, ((last === initWatchVal) ? value : last), current);
|
25089
25857
|
if (ttl < 5) {
|
25090
25858
|
logIdx = 4 - ttl;
|
25091
25859
|
if (!watchLog[logIdx]) watchLog[logIdx] = [];
|
@@ -25285,7 +26053,7 @@ function $RootScopeProvider() {
|
|
25285
26053
|
});
|
25286
26054
|
}
|
25287
26055
|
|
25288
|
-
asyncQueue.push({scope: this, expression: expr, locals: locals});
|
26056
|
+
asyncQueue.push({scope: this, expression: $parse(expr), locals: locals});
|
25289
26057
|
},
|
25290
26058
|
|
25291
26059
|
$$postDigest: function(fn) {
|
@@ -25377,6 +26145,7 @@ function $RootScopeProvider() {
|
|
25377
26145
|
$applyAsync: function(expr) {
|
25378
26146
|
var scope = this;
|
25379
26147
|
expr && applyAsyncQueue.push($applyAsyncExpression);
|
26148
|
+
expr = $parse(expr);
|
25380
26149
|
scheduleApplyAsync();
|
25381
26150
|
|
25382
26151
|
function $applyAsyncExpression() {
|
@@ -25651,6 +26420,21 @@ function $RootScopeProvider() {
|
|
25651
26420
|
}];
|
25652
26421
|
}
|
25653
26422
|
|
26423
|
+
/**
|
26424
|
+
* @ngdoc service
|
26425
|
+
* @name $rootElement
|
26426
|
+
*
|
26427
|
+
* @description
|
26428
|
+
* The root element of Angular application. This is either the element where {@link
|
26429
|
+
* ng.directive:ngApp ngApp} was declared or the element passed into
|
26430
|
+
* {@link angular.bootstrap}. The element represents the root element of application. It is also the
|
26431
|
+
* location where the application's {@link auto.$injector $injector} service gets
|
26432
|
+
* published, and can be retrieved using `$rootElement.injector()`.
|
26433
|
+
*/
|
26434
|
+
|
26435
|
+
|
26436
|
+
// the implementation is in angular.bootstrap
|
26437
|
+
|
25654
26438
|
/**
|
25655
26439
|
* @description
|
25656
26440
|
* Private service to sanitize uris for links and images. Used by $compile and $sanitize.
|
@@ -25865,13 +26649,15 @@ function $SceDelegateProvider() {
|
|
25865
26649
|
* @kind function
|
25866
26650
|
*
|
25867
26651
|
* @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
|
25868
|
-
*
|
25869
|
-
*
|
26652
|
+
* provided. This must be an array or null. A snapshot of this array is used so further
|
26653
|
+
* changes to the array are ignored.
|
25870
26654
|
*
|
25871
|
-
*
|
25872
|
-
*
|
26655
|
+
* Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
|
26656
|
+
* allowed in this array.
|
25873
26657
|
*
|
25874
|
-
*
|
26658
|
+
* <div class="alert alert-warning">
|
26659
|
+
* **Note:** an empty whitelist array will block all URLs!
|
26660
|
+
* </div>
|
25875
26661
|
*
|
25876
26662
|
* @return {Array} the currently set whitelist array.
|
25877
26663
|
*
|
@@ -25894,17 +26680,17 @@ function $SceDelegateProvider() {
|
|
25894
26680
|
* @kind function
|
25895
26681
|
*
|
25896
26682
|
* @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
|
25897
|
-
*
|
25898
|
-
*
|
26683
|
+
* provided. This must be an array or null. A snapshot of this array is used so further
|
26684
|
+
* changes to the array are ignored.
|
25899
26685
|
*
|
25900
|
-
*
|
25901
|
-
*
|
26686
|
+
* Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
|
26687
|
+
* allowed in this array.
|
25902
26688
|
*
|
25903
|
-
*
|
25904
|
-
*
|
25905
|
-
*
|
26689
|
+
* The typical usage for the blacklist is to **block
|
26690
|
+
* [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
|
26691
|
+
* these would otherwise be trusted but actually return content from the redirected domain.
|
25906
26692
|
*
|
25907
|
-
*
|
26693
|
+
* Finally, **the blacklist overrides the whitelist** and has the final say.
|
25908
26694
|
*
|
25909
26695
|
* @return {Array} the currently set blacklist array.
|
25910
26696
|
*
|
@@ -26063,6 +26849,11 @@ function $SceDelegateProvider() {
|
|
26063
26849
|
* returns the originally supplied value if the queried context type is a supertype of the
|
26064
26850
|
* created type. If this condition isn't satisfied, throws an exception.
|
26065
26851
|
*
|
26852
|
+
* <div class="alert alert-danger">
|
26853
|
+
* Disabling auto-escaping is extremely dangerous, it usually creates a Cross Site Scripting
|
26854
|
+
* (XSS) vulnerability in your application.
|
26855
|
+
* </div>
|
26856
|
+
*
|
26066
26857
|
* @param {string} type The kind of context in which this value is to be used.
|
26067
26858
|
* @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs
|
26068
26859
|
* `$sceDelegate.trustAs`} call.
|
@@ -26870,26 +27661,63 @@ function $SnifferProvider() {
|
|
26870
27661
|
var $compileMinErr = minErr('$compile');
|
26871
27662
|
|
26872
27663
|
/**
|
26873
|
-
* @ngdoc
|
26874
|
-
* @name $
|
26875
|
-
*
|
27664
|
+
* @ngdoc provider
|
27665
|
+
* @name $templateRequestProvider
|
26876
27666
|
* @description
|
26877
|
-
*
|
26878
|
-
* `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request
|
26879
|
-
* fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the
|
26880
|
-
* exception can be thwarted by setting the 2nd parameter of the function to true). Note that the
|
26881
|
-
* contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted
|
26882
|
-
* when `tpl` is of type string and `$templateCache` has the matching entry.
|
26883
|
-
*
|
26884
|
-
* @param {string|TrustedResourceUrl} tpl The HTTP request template URL
|
26885
|
-
* @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
|
27667
|
+
* Used to configure the options passed to the {@link $http} service when making a template request.
|
26886
27668
|
*
|
26887
|
-
*
|
26888
|
-
*
|
26889
|
-
* @property {number} totalPendingRequests total amount of pending template requests being downloaded.
|
27669
|
+
* For example, it can be used for specifying the "Accept" header that is sent to the server, when
|
27670
|
+
* requesting a template.
|
26890
27671
|
*/
|
26891
27672
|
function $TemplateRequestProvider() {
|
27673
|
+
|
27674
|
+
var httpOptions;
|
27675
|
+
|
27676
|
+
/**
|
27677
|
+
* @ngdoc method
|
27678
|
+
* @name $templateRequestProvider#httpOptions
|
27679
|
+
* @description
|
27680
|
+
* The options to be passed to the {@link $http} service when making the request.
|
27681
|
+
* You can use this to override options such as the "Accept" header for template requests.
|
27682
|
+
*
|
27683
|
+
* The {@link $templateRequest} will set the `cache` and the `transformResponse` properties of the
|
27684
|
+
* options if not overridden here.
|
27685
|
+
*
|
27686
|
+
* @param {string=} value new value for the {@link $http} options.
|
27687
|
+
* @returns {string|self} Returns the {@link $http} options when used as getter and self if used as setter.
|
27688
|
+
*/
|
27689
|
+
this.httpOptions = function(val) {
|
27690
|
+
if (val) {
|
27691
|
+
httpOptions = val;
|
27692
|
+
return this;
|
27693
|
+
}
|
27694
|
+
return httpOptions;
|
27695
|
+
};
|
27696
|
+
|
27697
|
+
/**
|
27698
|
+
* @ngdoc service
|
27699
|
+
* @name $templateRequest
|
27700
|
+
*
|
27701
|
+
* @description
|
27702
|
+
* The `$templateRequest` service runs security checks then downloads the provided template using
|
27703
|
+
* `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request
|
27704
|
+
* fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the
|
27705
|
+
* exception can be thwarted by setting the 2nd parameter of the function to true). Note that the
|
27706
|
+
* contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted
|
27707
|
+
* when `tpl` is of type string and `$templateCache` has the matching entry.
|
27708
|
+
*
|
27709
|
+
* If you want to pass custom options to the `$http` service, such as setting the Accept header you
|
27710
|
+
* can configure this via {@link $templateRequestProvider#httpOptions}.
|
27711
|
+
*
|
27712
|
+
* @param {string|TrustedResourceUrl} tpl The HTTP request template URL
|
27713
|
+
* @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
|
27714
|
+
*
|
27715
|
+
* @return {Promise} a promise for the HTTP response data of the given URL.
|
27716
|
+
*
|
27717
|
+
* @property {number} totalPendingRequests total amount of pending template requests being downloaded.
|
27718
|
+
*/
|
26892
27719
|
this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) {
|
27720
|
+
|
26893
27721
|
function handleRequestFn(tpl, ignoreRequestError) {
|
26894
27722
|
handleRequestFn.totalPendingRequests++;
|
26895
27723
|
|
@@ -26912,12 +27740,10 @@ function $TemplateRequestProvider() {
|
|
26912
27740
|
transformResponse = null;
|
26913
27741
|
}
|
26914
27742
|
|
26915
|
-
|
26916
|
-
|
26917
|
-
|
26918
|
-
|
26919
|
-
|
26920
|
-
return $http.get(tpl, httpOptions)
|
27743
|
+
return $http.get(tpl, extend({
|
27744
|
+
cache: $templateCache,
|
27745
|
+
transformResponse: transformResponse
|
27746
|
+
}, httpOptions))
|
26921
27747
|
['finally'](function() {
|
26922
27748
|
handleRequestFn.totalPendingRequests--;
|
26923
27749
|
})
|
@@ -27088,8 +27914,8 @@ function $TimeoutProvider() {
|
|
27088
27914
|
* @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
|
27089
27915
|
* will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
|
27090
27916
|
* @param {...*=} Pass additional parameters to the executed function.
|
27091
|
-
* @returns {Promise} Promise that will be resolved when the timeout is reached. The
|
27092
|
-
*
|
27917
|
+
* @returns {Promise} Promise that will be resolved when the timeout is reached. The promise
|
27918
|
+
* will be resolved with the return value of the `fn` function.
|
27093
27919
|
*
|
27094
27920
|
*/
|
27095
27921
|
function timeout(fn, delay, invokeApply) {
|
@@ -27765,6 +28591,10 @@ function getTypeForFilter(val) {
|
|
27765
28591
|
return (val === null) ? 'null' : typeof val;
|
27766
28592
|
}
|
27767
28593
|
|
28594
|
+
var MAX_DIGITS = 22;
|
28595
|
+
var DECIMAL_SEP = '.';
|
28596
|
+
var ZERO_CHAR = '0';
|
28597
|
+
|
27768
28598
|
/**
|
27769
28599
|
* @ngdoc filter
|
27770
28600
|
* @name currency
|
@@ -27854,7 +28684,7 @@ function currencyFilter($locale) {
|
|
27854
28684
|
* @param {(number|string)=} fractionSize Number of decimal places to round the number to.
|
27855
28685
|
* If this is not provided then the fraction size is computed from the current locale's number
|
27856
28686
|
* formatting pattern. In the case of the default locale, it will be 3.
|
27857
|
-
* @returns {string} Number rounded to
|
28687
|
+
* @returns {string} Number rounded to fractionSize and places a “,” after each third digit.
|
27858
28688
|
*
|
27859
28689
|
* @example
|
27860
28690
|
<example module="numberFilterExample">
|
@@ -27889,8 +28719,6 @@ function currencyFilter($locale) {
|
|
27889
28719
|
</file>
|
27890
28720
|
</example>
|
27891
28721
|
*/
|
27892
|
-
|
27893
|
-
|
27894
28722
|
numberFilter.$inject = ['$locale'];
|
27895
28723
|
function numberFilter($locale) {
|
27896
28724
|
var formats = $locale.NUMBER_FORMATS;
|
@@ -27904,93 +28732,194 @@ function numberFilter($locale) {
|
|
27904
28732
|
};
|
27905
28733
|
}
|
27906
28734
|
|
27907
|
-
|
27908
|
-
|
27909
|
-
|
28735
|
+
/**
|
28736
|
+
* Parse a number (as a string) into three components that can be used
|
28737
|
+
* for formatting the number.
|
28738
|
+
*
|
28739
|
+
* (Significant bits of this parse algorithm came from https://github.com/MikeMcl/big.js/)
|
28740
|
+
*
|
28741
|
+
* @param {string} numStr The number to parse
|
28742
|
+
* @return {object} An object describing this number, containing the following keys:
|
28743
|
+
* - d : an array of digits containing leading zeros as necessary
|
28744
|
+
* - i : the number of the digits in `d` that are to the left of the decimal point
|
28745
|
+
* - e : the exponent for numbers that would need more than `MAX_DIGITS` digits in `d`
|
28746
|
+
*
|
28747
|
+
*/
|
28748
|
+
function parse(numStr) {
|
28749
|
+
var exponent = 0, digits, numberOfIntegerDigits;
|
28750
|
+
var i, j, zeros;
|
27910
28751
|
|
27911
|
-
|
27912
|
-
|
28752
|
+
// Decimal point?
|
28753
|
+
if ((numberOfIntegerDigits = numStr.indexOf(DECIMAL_SEP)) > -1) {
|
28754
|
+
numStr = numStr.replace(DECIMAL_SEP, '');
|
28755
|
+
}
|
27913
28756
|
|
27914
|
-
|
27915
|
-
if (
|
28757
|
+
// Exponential form?
|
28758
|
+
if ((i = numStr.search(/e/i)) > 0) {
|
28759
|
+
// Work out the exponent.
|
28760
|
+
if (numberOfIntegerDigits < 0) numberOfIntegerDigits = i;
|
28761
|
+
numberOfIntegerDigits += +numStr.slice(i + 1);
|
28762
|
+
numStr = numStr.substring(0, i);
|
28763
|
+
} else if (numberOfIntegerDigits < 0) {
|
28764
|
+
// There was no decimal point or exponent so it is an integer.
|
28765
|
+
numberOfIntegerDigits = numStr.length;
|
28766
|
+
}
|
27916
28767
|
|
27917
|
-
|
27918
|
-
|
27919
|
-
hasExponent = false,
|
27920
|
-
parts = [];
|
28768
|
+
// Count the number of leading zeros.
|
28769
|
+
for (i = 0; numStr.charAt(i) == ZERO_CHAR; i++);
|
27921
28770
|
|
27922
|
-
if (
|
28771
|
+
if (i == (zeros = numStr.length)) {
|
28772
|
+
// The digits are all zero.
|
28773
|
+
digits = [0];
|
28774
|
+
numberOfIntegerDigits = 1;
|
28775
|
+
} else {
|
28776
|
+
// Count the number of trailing zeros
|
28777
|
+
zeros--;
|
28778
|
+
while (numStr.charAt(zeros) == ZERO_CHAR) zeros--;
|
27923
28779
|
|
27924
|
-
|
27925
|
-
|
27926
|
-
|
27927
|
-
|
27928
|
-
|
27929
|
-
|
27930
|
-
hasExponent = true;
|
28780
|
+
// Trailing zeros are insignificant so ignore them
|
28781
|
+
numberOfIntegerDigits -= i;
|
28782
|
+
digits = [];
|
28783
|
+
// Convert string to array of digits without leading/trailing zeros.
|
28784
|
+
for (j = 0; i <= zeros; i++, j++) {
|
28785
|
+
digits[j] = +numStr.charAt(i);
|
27931
28786
|
}
|
27932
28787
|
}
|
27933
28788
|
|
27934
|
-
|
27935
|
-
|
28789
|
+
// If the number overflows the maximum allowed digits then use an exponent.
|
28790
|
+
if (numberOfIntegerDigits > MAX_DIGITS) {
|
28791
|
+
digits = digits.splice(0, MAX_DIGITS - 1);
|
28792
|
+
exponent = numberOfIntegerDigits - 1;
|
28793
|
+
numberOfIntegerDigits = 1;
|
28794
|
+
}
|
27936
28795
|
|
27937
|
-
|
27938
|
-
|
27939
|
-
|
28796
|
+
return { d: digits, e: exponent, i: numberOfIntegerDigits };
|
28797
|
+
}
|
28798
|
+
|
28799
|
+
/**
|
28800
|
+
* Round the parsed number to the specified number of decimal places
|
28801
|
+
* This function changed the parsedNumber in-place
|
28802
|
+
*/
|
28803
|
+
function roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) {
|
28804
|
+
var digits = parsedNumber.d;
|
28805
|
+
var fractionLen = digits.length - parsedNumber.i;
|
28806
|
+
|
28807
|
+
// determine fractionSize if it is not specified; `+fractionSize` converts it to a number
|
28808
|
+
fractionSize = (isUndefined(fractionSize)) ? Math.min(Math.max(minFrac, fractionLen), maxFrac) : +fractionSize;
|
28809
|
+
|
28810
|
+
// The index of the digit to where rounding is to occur
|
28811
|
+
var roundAt = fractionSize + parsedNumber.i;
|
28812
|
+
var digit = digits[roundAt];
|
28813
|
+
|
28814
|
+
if (roundAt > 0) {
|
28815
|
+
digits.splice(roundAt);
|
28816
|
+
} else {
|
28817
|
+
// We rounded to zero so reset the parsedNumber
|
28818
|
+
parsedNumber.i = 1;
|
28819
|
+
digits.length = roundAt = fractionSize + 1;
|
28820
|
+
for (var i=0; i < roundAt; i++) digits[i] = 0;
|
27940
28821
|
}
|
27941
28822
|
|
27942
|
-
|
27943
|
-
// inspired by:
|
27944
|
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
|
27945
|
-
number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
|
28823
|
+
if (digit >= 5) digits[roundAt - 1]++;
|
27946
28824
|
|
27947
|
-
|
27948
|
-
|
27949
|
-
fraction = fraction[1] || '';
|
28825
|
+
// Pad out with zeros to get the required fraction length
|
28826
|
+
for (; fractionLen < fractionSize; fractionLen++) digits.push(0);
|
27950
28827
|
|
27951
|
-
var i, pos = 0,
|
27952
|
-
lgroup = pattern.lgSize,
|
27953
|
-
group = pattern.gSize;
|
27954
28828
|
|
27955
|
-
|
27956
|
-
|
27957
|
-
|
27958
|
-
|
27959
|
-
|
27960
|
-
|
27961
|
-
|
27962
|
-
|
28829
|
+
// Do any carrying, e.g. a digit was rounded up to 10
|
28830
|
+
var carry = digits.reduceRight(function(carry, d, i, digits) {
|
28831
|
+
d = d + carry;
|
28832
|
+
digits[i] = d % 10;
|
28833
|
+
return Math.floor(d / 10);
|
28834
|
+
}, 0);
|
28835
|
+
if (carry) {
|
28836
|
+
digits.unshift(carry);
|
28837
|
+
parsedNumber.i++;
|
27963
28838
|
}
|
28839
|
+
}
|
27964
28840
|
|
27965
|
-
|
27966
|
-
|
27967
|
-
|
27968
|
-
|
27969
|
-
|
28841
|
+
/**
|
28842
|
+
* Format a number into a string
|
28843
|
+
* @param {number} number The number to format
|
28844
|
+
* @param {{
|
28845
|
+
* minFrac, // the minimum number of digits required in the fraction part of the number
|
28846
|
+
* maxFrac, // the maximum number of digits required in the fraction part of the number
|
28847
|
+
* gSize, // number of digits in each group of separated digits
|
28848
|
+
* lgSize, // number of digits in the last group of digits before the decimal separator
|
28849
|
+
* negPre, // the string to go in front of a negative number (e.g. `-` or `(`))
|
28850
|
+
* posPre, // the string to go in front of a positive number
|
28851
|
+
* negSuf, // the string to go after a negative number (e.g. `)`)
|
28852
|
+
* posSuf // the string to go after a positive number
|
28853
|
+
* }} pattern
|
28854
|
+
* @param {string} groupSep The string to separate groups of number (e.g. `,`)
|
28855
|
+
* @param {string} decimalSep The string to act as the decimal separator (e.g. `.`)
|
28856
|
+
* @param {[type]} fractionSize The size of the fractional part of the number
|
28857
|
+
* @return {string} The number formatted as a string
|
28858
|
+
*/
|
28859
|
+
function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
|
28860
|
+
|
28861
|
+
if (!(isString(number) || isNumber(number)) || isNaN(number)) return '';
|
28862
|
+
|
28863
|
+
var isInfinity = !isFinite(number);
|
28864
|
+
var isZero = false;
|
28865
|
+
var numStr = Math.abs(number) + '',
|
28866
|
+
formattedText = '',
|
28867
|
+
parsedNumber;
|
28868
|
+
|
28869
|
+
if (isInfinity) {
|
28870
|
+
formattedText = '\u221e';
|
28871
|
+
} else {
|
28872
|
+
parsedNumber = parse(numStr);
|
28873
|
+
|
28874
|
+
roundNumber(parsedNumber, fractionSize, pattern.minFrac, pattern.maxFrac);
|
28875
|
+
|
28876
|
+
var digits = parsedNumber.d;
|
28877
|
+
var integerLen = parsedNumber.i;
|
28878
|
+
var exponent = parsedNumber.e;
|
28879
|
+
var decimals = [];
|
28880
|
+
isZero = digits.reduce(function(isZero, d) { return isZero && !d; }, true);
|
28881
|
+
|
28882
|
+
// pad zeros for small numbers
|
28883
|
+
while (integerLen < 0) {
|
28884
|
+
digits.unshift(0);
|
28885
|
+
integerLen++;
|
27970
28886
|
}
|
27971
28887
|
|
27972
|
-
//
|
27973
|
-
|
27974
|
-
|
28888
|
+
// extract decimals digits
|
28889
|
+
if (integerLen > 0) {
|
28890
|
+
decimals = digits.splice(integerLen);
|
28891
|
+
} else {
|
28892
|
+
decimals = digits;
|
28893
|
+
digits = [0];
|
27975
28894
|
}
|
27976
28895
|
|
27977
|
-
|
27978
|
-
|
27979
|
-
if (
|
27980
|
-
|
27981
|
-
number = parseFloat(formatedText);
|
27982
|
-
formatedText = formatedText.replace(DECIMAL_SEP, decimalSep);
|
28896
|
+
// format the integer digits with grouping separators
|
28897
|
+
var groups = [];
|
28898
|
+
if (digits.length > pattern.lgSize) {
|
28899
|
+
groups.unshift(digits.splice(-pattern.lgSize).join(''));
|
27983
28900
|
}
|
27984
|
-
|
28901
|
+
while (digits.length > pattern.gSize) {
|
28902
|
+
groups.unshift(digits.splice(-pattern.gSize).join(''));
|
28903
|
+
}
|
28904
|
+
if (digits.length) {
|
28905
|
+
groups.unshift(digits.join(''));
|
28906
|
+
}
|
28907
|
+
formattedText = groups.join(groupSep);
|
27985
28908
|
|
27986
|
-
|
27987
|
-
|
27988
|
-
|
28909
|
+
// append the decimal digits
|
28910
|
+
if (decimals.length) {
|
28911
|
+
formattedText += decimalSep + decimals.join('');
|
28912
|
+
}
|
27989
28913
|
|
27990
|
-
|
27991
|
-
|
27992
|
-
|
27993
|
-
|
28914
|
+
if (exponent) {
|
28915
|
+
formattedText += 'e+' + exponent;
|
28916
|
+
}
|
28917
|
+
}
|
28918
|
+
if (number < 0 && !isZero) {
|
28919
|
+
return pattern.negPre + formattedText + pattern.negSuf;
|
28920
|
+
} else {
|
28921
|
+
return pattern.posPre + formattedText + pattern.posSuf;
|
28922
|
+
}
|
27994
28923
|
}
|
27995
28924
|
|
27996
28925
|
function padNumber(num, digits, trim) {
|
@@ -28000,7 +28929,7 @@ function padNumber(num, digits, trim) {
|
|
28000
28929
|
num = -num;
|
28001
28930
|
}
|
28002
28931
|
num = '' + num;
|
28003
|
-
while (num.length < digits) num =
|
28932
|
+
while (num.length < digits) num = ZERO_CHAR + num;
|
28004
28933
|
if (trim) {
|
28005
28934
|
num = num.substr(num.length - digits);
|
28006
28935
|
}
|
@@ -28269,13 +29198,13 @@ function dateFilter($locale) {
|
|
28269
29198
|
|
28270
29199
|
var dateTimezoneOffset = date.getTimezoneOffset();
|
28271
29200
|
if (timezone) {
|
28272
|
-
dateTimezoneOffset = timezoneToOffset(timezone,
|
29201
|
+
dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
|
28273
29202
|
date = convertTimezoneToLocal(date, timezone, true);
|
28274
29203
|
}
|
28275
29204
|
forEach(parts, function(value) {
|
28276
29205
|
fn = DATE_FORMATS[value];
|
28277
29206
|
text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset)
|
28278
|
-
: value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
|
29207
|
+
: value === "''" ? "'" : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
|
28279
29208
|
});
|
28280
29209
|
|
28281
29210
|
return text;
|
@@ -28479,8 +29408,9 @@ function limitToFilter() {
|
|
28479
29408
|
* Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
|
28480
29409
|
* for strings and numerically for numbers. Note: if you notice numbers are not being sorted
|
28481
29410
|
* as expected, make sure they are actually being saved as numbers and not strings.
|
29411
|
+
* Array-like values (e.g. NodeLists, jQuery objects, TypedArrays, Strings, etc) are also supported.
|
28482
29412
|
*
|
28483
|
-
* @param {Array} array The array to sort.
|
29413
|
+
* @param {Array} array The array (or array-like object) to sort.
|
28484
29414
|
* @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be
|
28485
29415
|
* used by the comparator to determine the order of elements.
|
28486
29416
|
*
|
@@ -28511,17 +29441,6 @@ function limitToFilter() {
|
|
28511
29441
|
* `reverse` is not set, which means it defaults to `false`.
|
28512
29442
|
<example module="orderByExample">
|
28513
29443
|
<file name="index.html">
|
28514
|
-
<script>
|
28515
|
-
angular.module('orderByExample', [])
|
28516
|
-
.controller('ExampleController', ['$scope', function($scope) {
|
28517
|
-
$scope.friends =
|
28518
|
-
[{name:'John', phone:'555-1212', age:10},
|
28519
|
-
{name:'Mary', phone:'555-9876', age:19},
|
28520
|
-
{name:'Mike', phone:'555-4321', age:21},
|
28521
|
-
{name:'Adam', phone:'555-5678', age:35},
|
28522
|
-
{name:'Julie', phone:'555-8765', age:29}];
|
28523
|
-
}]);
|
28524
|
-
</script>
|
28525
29444
|
<div ng-controller="ExampleController">
|
28526
29445
|
<table class="friend">
|
28527
29446
|
<tr>
|
@@ -28537,6 +29456,17 @@ function limitToFilter() {
|
|
28537
29456
|
</table>
|
28538
29457
|
</div>
|
28539
29458
|
</file>
|
29459
|
+
<file name="script.js">
|
29460
|
+
angular.module('orderByExample', [])
|
29461
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
29462
|
+
$scope.friends =
|
29463
|
+
[{name:'John', phone:'555-1212', age:10},
|
29464
|
+
{name:'Mary', phone:'555-9876', age:19},
|
29465
|
+
{name:'Mike', phone:'555-4321', age:21},
|
29466
|
+
{name:'Adam', phone:'555-5678', age:35},
|
29467
|
+
{name:'Julie', phone:'555-8765', age:29}];
|
29468
|
+
}]);
|
29469
|
+
</file>
|
28540
29470
|
</example>
|
28541
29471
|
*
|
28542
29472
|
* The predicate and reverse parameters can be controlled dynamically through scope properties,
|
@@ -28544,49 +29474,24 @@ function limitToFilter() {
|
|
28544
29474
|
* @example
|
28545
29475
|
<example module="orderByExample">
|
28546
29476
|
<file name="index.html">
|
28547
|
-
<script>
|
28548
|
-
angular.module('orderByExample', [])
|
28549
|
-
.controller('ExampleController', ['$scope', function($scope) {
|
28550
|
-
$scope.friends =
|
28551
|
-
[{name:'John', phone:'555-1212', age:10},
|
28552
|
-
{name:'Mary', phone:'555-9876', age:19},
|
28553
|
-
{name:'Mike', phone:'555-4321', age:21},
|
28554
|
-
{name:'Adam', phone:'555-5678', age:35},
|
28555
|
-
{name:'Julie', phone:'555-8765', age:29}];
|
28556
|
-
$scope.predicate = 'age';
|
28557
|
-
$scope.reverse = true;
|
28558
|
-
$scope.order = function(predicate) {
|
28559
|
-
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
|
28560
|
-
$scope.predicate = predicate;
|
28561
|
-
};
|
28562
|
-
}]);
|
28563
|
-
</script>
|
28564
|
-
<style type="text/css">
|
28565
|
-
.sortorder:after {
|
28566
|
-
content: '\25b2';
|
28567
|
-
}
|
28568
|
-
.sortorder.reverse:after {
|
28569
|
-
content: '\25bc';
|
28570
|
-
}
|
28571
|
-
</style>
|
28572
29477
|
<div ng-controller="ExampleController">
|
28573
29478
|
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
|
28574
29479
|
<hr/>
|
28575
|
-
|
29480
|
+
<button ng-click="predicate=''">Set to unsorted</button>
|
28576
29481
|
<table class="friend">
|
28577
29482
|
<tr>
|
28578
|
-
|
28579
|
-
|
28580
|
-
|
28581
|
-
|
28582
|
-
|
28583
|
-
|
28584
|
-
|
28585
|
-
|
28586
|
-
|
28587
|
-
|
28588
|
-
|
28589
|
-
|
29483
|
+
<th>
|
29484
|
+
<button ng-click="order('name')">Name</button>
|
29485
|
+
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
29486
|
+
</th>
|
29487
|
+
<th>
|
29488
|
+
<button ng-click="order('phone')">Phone Number</button>
|
29489
|
+
<span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
|
29490
|
+
</th>
|
29491
|
+
<th>
|
29492
|
+
<button ng-click="order('age')">Age</button>
|
29493
|
+
<span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
|
29494
|
+
</th>
|
28590
29495
|
</tr>
|
28591
29496
|
<tr ng-repeat="friend in friends | orderBy:predicate:reverse">
|
28592
29497
|
<td>{{friend.name}}</td>
|
@@ -28596,6 +29501,31 @@ function limitToFilter() {
|
|
28596
29501
|
</table>
|
28597
29502
|
</div>
|
28598
29503
|
</file>
|
29504
|
+
<file name="script.js">
|
29505
|
+
angular.module('orderByExample', [])
|
29506
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
29507
|
+
$scope.friends =
|
29508
|
+
[{name:'John', phone:'555-1212', age:10},
|
29509
|
+
{name:'Mary', phone:'555-9876', age:19},
|
29510
|
+
{name:'Mike', phone:'555-4321', age:21},
|
29511
|
+
{name:'Adam', phone:'555-5678', age:35},
|
29512
|
+
{name:'Julie', phone:'555-8765', age:29}];
|
29513
|
+
$scope.predicate = 'age';
|
29514
|
+
$scope.reverse = true;
|
29515
|
+
$scope.order = function(predicate) {
|
29516
|
+
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
|
29517
|
+
$scope.predicate = predicate;
|
29518
|
+
};
|
29519
|
+
}]);
|
29520
|
+
</file>
|
29521
|
+
<file name="style.css">
|
29522
|
+
.sortorder:after {
|
29523
|
+
content: '\25b2';
|
29524
|
+
}
|
29525
|
+
.sortorder.reverse:after {
|
29526
|
+
content: '\25bc';
|
29527
|
+
}
|
29528
|
+
</file>
|
28599
29529
|
</example>
|
28600
29530
|
*
|
28601
29531
|
* It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
|
@@ -28607,21 +29537,30 @@ function limitToFilter() {
|
|
28607
29537
|
* @example
|
28608
29538
|
<example module="orderByExample">
|
28609
29539
|
<file name="index.html">
|
28610
|
-
|
28611
|
-
|
28612
|
-
|
28613
|
-
|
28614
|
-
|
28615
|
-
|
28616
|
-
|
28617
|
-
</
|
28618
|
-
<
|
28619
|
-
|
28620
|
-
|
28621
|
-
|
28622
|
-
|
28623
|
-
|
28624
|
-
|
29540
|
+
<div ng-controller="ExampleController">
|
29541
|
+
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
|
29542
|
+
<table class="friend">
|
29543
|
+
<tr>
|
29544
|
+
<th>
|
29545
|
+
<button ng-click="order('name')">Name</button>
|
29546
|
+
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
29547
|
+
</th>
|
29548
|
+
<th>
|
29549
|
+
<button ng-click="order('phone')">Phone Number</button>
|
29550
|
+
<span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
|
29551
|
+
</th>
|
29552
|
+
<th>
|
29553
|
+
<button ng-click="order('age')">Age</button>
|
29554
|
+
<span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
|
29555
|
+
</th>
|
29556
|
+
</tr>
|
29557
|
+
<tr ng-repeat="friend in friends">
|
29558
|
+
<td>{{friend.name}}</td>
|
29559
|
+
<td>{{friend.phone}}</td>
|
29560
|
+
<td>{{friend.age}}</td>
|
29561
|
+
</tr>
|
29562
|
+
</table>
|
29563
|
+
</div>
|
28625
29564
|
</file>
|
28626
29565
|
|
28627
29566
|
<file name="script.js">
|
@@ -28635,19 +29574,33 @@ function limitToFilter() {
|
|
28635
29574
|
{ name: 'Adam', phone: '555-5678', age: 35 },
|
28636
29575
|
{ name: 'Julie', phone: '555-8765', age: 29 }
|
28637
29576
|
];
|
28638
|
-
$scope.order = function(predicate
|
28639
|
-
$scope.
|
29577
|
+
$scope.order = function(predicate) {
|
29578
|
+
$scope.predicate = predicate;
|
29579
|
+
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
|
29580
|
+
$scope.friends = orderBy($scope.friends, predicate, $scope.reverse);
|
28640
29581
|
};
|
28641
|
-
$scope.order('
|
29582
|
+
$scope.order('age', true);
|
28642
29583
|
}]);
|
28643
29584
|
</file>
|
29585
|
+
|
29586
|
+
<file name="style.css">
|
29587
|
+
.sortorder:after {
|
29588
|
+
content: '\25b2';
|
29589
|
+
}
|
29590
|
+
.sortorder.reverse:after {
|
29591
|
+
content: '\25bc';
|
29592
|
+
}
|
29593
|
+
</file>
|
28644
29594
|
</example>
|
28645
29595
|
*/
|
28646
29596
|
orderByFilter.$inject = ['$parse'];
|
28647
29597
|
function orderByFilter($parse) {
|
28648
29598
|
return function(array, sortPredicate, reverseOrder) {
|
28649
29599
|
|
28650
|
-
if (
|
29600
|
+
if (array == null) return array;
|
29601
|
+
if (!isArrayLike(array)) {
|
29602
|
+
throw minErr('orderBy')('notarray', 'Expected array but received: {0}', array);
|
29603
|
+
}
|
28651
29604
|
|
28652
29605
|
if (!isArray(sortPredicate)) { sortPredicate = [sortPredicate]; }
|
28653
29606
|
if (sortPredicate.length === 0) { sortPredicate = ['+']; }
|
@@ -28970,20 +29923,7 @@ var htmlAnchorDirective = valueFn({
|
|
28970
29923
|
* {@link guide/expression expression} inside `ngDisabled` evaluates to truthy.
|
28971
29924
|
*
|
28972
29925
|
* A special directive is necessary because we cannot use interpolation inside the `disabled`
|
28973
|
-
* attribute.
|
28974
|
-
* but not on older IEs:
|
28975
|
-
*
|
28976
|
-
* ```html
|
28977
|
-
* <!-- See below for an example of ng-disabled being used correctly -->
|
28978
|
-
* <div ng-init="isDisabled = false">
|
28979
|
-
* <button disabled="{{isDisabled}}">Disabled</button>
|
28980
|
-
* </div>
|
28981
|
-
* ```
|
28982
|
-
*
|
28983
|
-
* This is because the HTML specification does not require browsers to preserve the values of
|
28984
|
-
* boolean attributes such as `disabled` (Their presence means true and their absence means false.)
|
28985
|
-
* If we put an Angular interpolation expression into such an attribute then the
|
28986
|
-
* binding information would be lost when the browser removes the attribute.
|
29926
|
+
* attribute. See the {@link guide/interpolation interpolation guide} for more info.
|
28987
29927
|
*
|
28988
29928
|
* @example
|
28989
29929
|
<example>
|
@@ -29018,15 +29958,9 @@ var htmlAnchorDirective = valueFn({
|
|
29018
29958
|
* Note that this directive should not be used together with {@link ngModel `ngModel`},
|
29019
29959
|
* as this can lead to unexpected behavior.
|
29020
29960
|
*
|
29021
|
-
*
|
29961
|
+
* A special directive is necessary because we cannot use interpolation inside the `checked`
|
29962
|
+
* attribute. See the {@link guide/interpolation interpolation guide} for more info.
|
29022
29963
|
*
|
29023
|
-
* The HTML specification does not require browsers to preserve the values of boolean attributes
|
29024
|
-
* such as checked. (Their presence means true and their absence means false.)
|
29025
|
-
* If we put an Angular interpolation expression into such an attribute then the
|
29026
|
-
* binding information would be lost when the browser removes the attribute.
|
29027
|
-
* The `ngChecked` directive solves this problem for the `checked` attribute.
|
29028
|
-
* This complementary directive is not removed by the browser and so provides
|
29029
|
-
* a permanent reliable place to store the binding information.
|
29030
29964
|
* @example
|
29031
29965
|
<example>
|
29032
29966
|
<file name="index.html">
|
@@ -29055,13 +29989,12 @@ var htmlAnchorDirective = valueFn({
|
|
29055
29989
|
* @priority 100
|
29056
29990
|
*
|
29057
29991
|
* @description
|
29058
|
-
*
|
29059
|
-
*
|
29060
|
-
*
|
29061
|
-
*
|
29062
|
-
*
|
29063
|
-
*
|
29064
|
-
* a permanent reliable place to store the binding information.
|
29992
|
+
*
|
29993
|
+
* Sets the `readOnly` attribute on the element, if the expression inside `ngReadonly` is truthy.
|
29994
|
+
*
|
29995
|
+
* A special directive is necessary because we cannot use interpolation inside the `readOnly`
|
29996
|
+
* attribute. See the {@link guide/interpolation interpolation guide} for more info.
|
29997
|
+
*
|
29065
29998
|
* @example
|
29066
29999
|
<example>
|
29067
30000
|
<file name="index.html">
|
@@ -29090,13 +30023,11 @@ var htmlAnchorDirective = valueFn({
|
|
29090
30023
|
* @priority 100
|
29091
30024
|
*
|
29092
30025
|
* @description
|
29093
|
-
*
|
29094
|
-
*
|
29095
|
-
*
|
29096
|
-
*
|
29097
|
-
*
|
29098
|
-
* This complementary directive is not removed by the browser and so provides
|
29099
|
-
* a permanent reliable place to store the binding information.
|
30026
|
+
*
|
30027
|
+
* Sets the `selected` attribute on the element, if the expression inside `ngSelected` is truthy.
|
30028
|
+
*
|
30029
|
+
* A special directive is necessary because we cannot use interpolation inside the `selected`
|
30030
|
+
* attribute. See the {@link guide/interpolation interpolation guide} for more info.
|
29100
30031
|
*
|
29101
30032
|
* @example
|
29102
30033
|
<example>
|
@@ -29128,13 +30059,12 @@ var htmlAnchorDirective = valueFn({
|
|
29128
30059
|
* @priority 100
|
29129
30060
|
*
|
29130
30061
|
* @description
|
29131
|
-
*
|
29132
|
-
*
|
29133
|
-
*
|
29134
|
-
*
|
29135
|
-
*
|
29136
|
-
*
|
29137
|
-
* a permanent reliable place to store the binding information.
|
30062
|
+
*
|
30063
|
+
* Sets the `open` attribute on the element, if the expression inside `ngOpen` is truthy.
|
30064
|
+
*
|
30065
|
+
* A special directive is necessary because we cannot use interpolation inside the `open`
|
30066
|
+
* attribute. See the {@link guide/interpolation interpolation guide} for more info.
|
30067
|
+
*
|
29138
30068
|
* @example
|
29139
30069
|
<example>
|
29140
30070
|
<file name="index.html">
|
@@ -29380,7 +30310,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
|
29380
30310
|
*
|
29381
30311
|
* However, if the method is used programmatically, for example by adding dynamically created controls,
|
29382
30312
|
* or controls that have been previously removed without destroying their corresponding DOM element,
|
29383
|
-
* it's the developers
|
30313
|
+
* it's the developers responsibility to make sure the current state propagates to the parent form.
|
29384
30314
|
*
|
29385
30315
|
* For example, if an input control is added that is already `$dirty` and has `$error` properties,
|
29386
30316
|
* calling `$setDirty()` and `$validate()` afterwards will propagate the state to the parent form.
|
@@ -29590,13 +30520,9 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
|
29590
30520
|
*
|
29591
30521
|
* In Angular, forms can be nested. This means that the outer form is valid when all of the child
|
29592
30522
|
* forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
|
29593
|
-
* Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to
|
29594
|
-
*
|
29595
|
-
*
|
29596
|
-
* {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`
|
29597
|
-
* attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an
|
29598
|
-
* `ngForm` directive and nest these in an outer `form` element.
|
29599
|
-
*
|
30523
|
+
* Angular provides the {@link ng.directive:ngForm `ngForm`} directive, which behaves identically to
|
30524
|
+
* `form` but can be nested. Nested forms can be useful, for example, if the validity of a sub-group
|
30525
|
+
* of controls needs to be determined.
|
29600
30526
|
*
|
29601
30527
|
* # CSS classes
|
29602
30528
|
* - `ng-valid` is set if the form is valid.
|
@@ -29817,7 +30743,18 @@ var ngFormDirective = formDirectiveFactory(true);
|
|
29817
30743
|
// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231
|
29818
30744
|
var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/;
|
29819
30745
|
// See valid URLs in RFC3987 (http://tools.ietf.org/html/rfc3987)
|
29820
|
-
|
30746
|
+
// Note: We are being more lenient, because browsers are too.
|
30747
|
+
// 1. Scheme
|
30748
|
+
// 2. Slashes
|
30749
|
+
// 3. Username
|
30750
|
+
// 4. Password
|
30751
|
+
// 5. Hostname
|
30752
|
+
// 6. Port
|
30753
|
+
// 7. Path
|
30754
|
+
// 8. Query
|
30755
|
+
// 9. Fragment
|
30756
|
+
// 1111111111111111 222 333333 44444 555555555555555555555555 666 77777777 8888888 999
|
30757
|
+
var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i;
|
29821
30758
|
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;
|
29822
30759
|
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/;
|
29823
30760
|
var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
|
@@ -29850,8 +30787,8 @@ var inputType = {
|
|
29850
30787
|
* @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
|
29851
30788
|
* that contains the regular expression body that will be converted to a regular expression
|
29852
30789
|
* as in the ngPattern directive.
|
29853
|
-
* @param {string=} ngPattern Sets `pattern` validation error key if the ngModel
|
29854
|
-
* a RegExp found by evaluating the Angular expression given in the attribute value.
|
30790
|
+
* @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
|
30791
|
+
* does not match a RegExp found by evaluating the Angular expression given in the attribute value.
|
29855
30792
|
* If the expression evaluates to a RegExp object, then this is used directly.
|
29856
30793
|
* If the expression evaluates to a string, then it will be converted to a RegExp
|
29857
30794
|
* after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
|
@@ -30138,7 +31075,7 @@ var inputType = {
|
|
30138
31075
|
*
|
30139
31076
|
* @description
|
30140
31077
|
* Input with time validation and transformation. In browsers that do not yet support
|
30141
|
-
* the HTML5
|
31078
|
+
* the HTML5 time input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
|
30142
31079
|
* local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a
|
30143
31080
|
* Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.
|
30144
31081
|
*
|
@@ -30485,8 +31422,8 @@ var inputType = {
|
|
30485
31422
|
* @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
|
30486
31423
|
* that contains the regular expression body that will be converted to a regular expression
|
30487
31424
|
* as in the ngPattern directive.
|
30488
|
-
* @param {string=} ngPattern Sets `pattern` validation error key if the ngModel
|
30489
|
-
* a RegExp found by evaluating the Angular expression given in the attribute value.
|
31425
|
+
* @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
|
31426
|
+
* does not match a RegExp found by evaluating the Angular expression given in the attribute value.
|
30490
31427
|
* If the expression evaluates to a RegExp object, then this is used directly.
|
30491
31428
|
* If the expression evaluates to a string, then it will be converted to a RegExp
|
30492
31429
|
* after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
|
@@ -30583,8 +31520,8 @@ var inputType = {
|
|
30583
31520
|
* @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
|
30584
31521
|
* that contains the regular expression body that will be converted to a regular expression
|
30585
31522
|
* as in the ngPattern directive.
|
30586
|
-
* @param {string=} ngPattern Sets `pattern` validation error key if the ngModel
|
30587
|
-
* a RegExp found by evaluating the Angular expression given in the attribute value.
|
31523
|
+
* @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
|
31524
|
+
* does not match a RegExp found by evaluating the Angular expression given in the attribute value.
|
30588
31525
|
* If the expression evaluates to a RegExp object, then this is used directly.
|
30589
31526
|
* If the expression evaluates to a string, then it will be converted to a RegExp
|
30590
31527
|
* after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
|
@@ -30682,8 +31619,8 @@ var inputType = {
|
|
30682
31619
|
* @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
|
30683
31620
|
* that contains the regular expression body that will be converted to a regular expression
|
30684
31621
|
* as in the ngPattern directive.
|
30685
|
-
* @param {string=} ngPattern Sets `pattern` validation error key if the ngModel
|
30686
|
-
* a RegExp found by evaluating the Angular expression given in the attribute value.
|
31622
|
+
* @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
|
31623
|
+
* does not match a RegExp found by evaluating the Angular expression given in the attribute value.
|
30687
31624
|
* If the expression evaluates to a RegExp object, then this is used directly.
|
30688
31625
|
* If the expression evaluates to a string, then it will be converted to a RegExp
|
30689
31626
|
* after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
|
@@ -31143,11 +32080,7 @@ function badInputChecker(scope, element, attr, ctrl) {
|
|
31143
32080
|
if (nativeValidation) {
|
31144
32081
|
ctrl.$parsers.push(function(value) {
|
31145
32082
|
var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};
|
31146
|
-
|
31147
|
-
// - also sets validity.badInput (should only be validity.typeMismatch).
|
31148
|
-
// - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email)
|
31149
|
-
// - can ignore this case as we can still read out the erroneous email...
|
31150
|
-
return validity.badInput && !validity.typeMismatch ? undefined : value;
|
32083
|
+
return validity.badInput || validity.typeMismatch ? undefined : value;
|
31151
32084
|
});
|
31152
32085
|
}
|
31153
32086
|
}
|
@@ -31319,8 +32252,8 @@ function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filt
|
|
31319
32252
|
* @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
|
31320
32253
|
* maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
|
31321
32254
|
* length.
|
31322
|
-
* @param {string=} ngPattern Sets `pattern` validation error key if the ngModel
|
31323
|
-
* a RegExp found by evaluating the Angular expression given in the attribute value.
|
32255
|
+
* @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
|
32256
|
+
* does not match a RegExp found by evaluating the Angular expression given in the attribute value.
|
31324
32257
|
* If the expression evaluates to a RegExp object, then this is used directly.
|
31325
32258
|
* If the expression evaluates to a string, then it will be converted to a RegExp
|
31326
32259
|
* after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
|
@@ -31358,8 +32291,8 @@ function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filt
|
|
31358
32291
|
* @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
|
31359
32292
|
* maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
|
31360
32293
|
* length.
|
31361
|
-
* @param {string=} ngPattern Sets `pattern` validation error key if the ngModel
|
31362
|
-
* a RegExp found by evaluating the Angular expression given in the attribute value.
|
32294
|
+
* @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
|
32295
|
+
* value does not match a RegExp found by evaluating the Angular expression given in the attribute value.
|
31363
32296
|
* If the expression evaluates to a RegExp object, then this is used directly.
|
31364
32297
|
* If the expression evaluates to a string, then it will be converted to a RegExp
|
31365
32298
|
* after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
|
@@ -32585,7 +33518,7 @@ var ngControllerDirective = [function() {
|
|
32585
33518
|
*
|
32586
33519
|
* * no-inline-style: this stops Angular from injecting CSS styles into the DOM
|
32587
33520
|
*
|
32588
|
-
* * no-unsafe-eval: this stops Angular from
|
33521
|
+
* * no-unsafe-eval: this stops Angular from optimizing $parse with unsafe eval of strings
|
32589
33522
|
*
|
32590
33523
|
* You can use these values in the following combinations:
|
32591
33524
|
*
|
@@ -32602,7 +33535,7 @@ var ngControllerDirective = [function() {
|
|
32602
33535
|
* inline styles. E.g. `<body ng-csp="no-unsafe-eval">`.
|
32603
33536
|
*
|
32604
33537
|
* * Specifying only `no-inline-style` tells Angular that we must not inject styles, but that we can
|
32605
|
-
* run eval - no
|
33538
|
+
* run eval - no automatic check for unsafe eval will occur. E.g. `<body ng-csp="no-inline-style">`
|
32606
33539
|
*
|
32607
33540
|
* * Specifying both `no-unsafe-eval` and `no-inline-style` tells Angular that we must not inject
|
32608
33541
|
* styles nor use eval, which is the same as an empty: ng-csp.
|
@@ -33581,6 +34514,8 @@ var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
|
|
33581
34514
|
//set the 2nd param to true to ignore the template request error so that the inner
|
33582
34515
|
//contents and scope can be cleaned up.
|
33583
34516
|
$templateRequest(src, true).then(function(response) {
|
34517
|
+
if (scope.$$destroyed) return;
|
34518
|
+
|
33584
34519
|
if (thisChangeId !== changeCounter) return;
|
33585
34520
|
var newScope = scope.$new();
|
33586
34521
|
ctrl.template = response;
|
@@ -33602,6 +34537,8 @@ var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
|
|
33602
34537
|
currentScope.$emit('$includeContentLoaded', src);
|
33603
34538
|
scope.$eval(onloadExp);
|
33604
34539
|
}, function() {
|
34540
|
+
if (scope.$$destroyed) return;
|
34541
|
+
|
33605
34542
|
if (thisChangeId === changeCounter) {
|
33606
34543
|
cleanupLastIncludeContent();
|
33607
34544
|
scope.$emit('$includeContentError', src);
|
@@ -33630,7 +34567,7 @@ var ngIncludeFillContentDirective = ['$compile',
|
|
33630
34567
|
priority: -400,
|
33631
34568
|
require: 'ngInclude',
|
33632
34569
|
link: function(scope, $element, $attr, ctrl) {
|
33633
|
-
if (
|
34570
|
+
if (toString.call($element[0]).match(/SVG/)) {
|
33634
34571
|
// WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not
|
33635
34572
|
// support innerHTML, so detect this here and try to generate the contents
|
33636
34573
|
// specially.
|
@@ -33859,7 +34796,9 @@ var VALID_CLASS = 'ng-valid',
|
|
33859
34796
|
DIRTY_CLASS = 'ng-dirty',
|
33860
34797
|
UNTOUCHED_CLASS = 'ng-untouched',
|
33861
34798
|
TOUCHED_CLASS = 'ng-touched',
|
33862
|
-
PENDING_CLASS = 'ng-pending'
|
34799
|
+
PENDING_CLASS = 'ng-pending',
|
34800
|
+
EMPTY_CLASS = 'ng-empty',
|
34801
|
+
NOT_EMPTY_CLASS = 'ng-not-empty';
|
33863
34802
|
|
33864
34803
|
var ngModelMinErr = minErr('ngModel');
|
33865
34804
|
|
@@ -34163,6 +35102,17 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
34163
35102
|
return isUndefined(value) || value === '' || value === null || value !== value;
|
34164
35103
|
};
|
34165
35104
|
|
35105
|
+
this.$$updateEmptyClasses = function(value) {
|
35106
|
+
if (ctrl.$isEmpty(value)) {
|
35107
|
+
$animate.removeClass($element, NOT_EMPTY_CLASS);
|
35108
|
+
$animate.addClass($element, EMPTY_CLASS);
|
35109
|
+
} else {
|
35110
|
+
$animate.removeClass($element, EMPTY_CLASS);
|
35111
|
+
$animate.addClass($element, NOT_EMPTY_CLASS);
|
35112
|
+
}
|
35113
|
+
};
|
35114
|
+
|
35115
|
+
|
34166
35116
|
var currentValidationRunId = 0;
|
34167
35117
|
|
34168
35118
|
/**
|
@@ -34280,11 +35230,14 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
34280
35230
|
* which may be caused by a pending debounced event or because the input is waiting for a some
|
34281
35231
|
* future event.
|
34282
35232
|
*
|
34283
|
-
* If you have an input that uses `ng-model-options` to set up debounced
|
34284
|
-
* as blur you can have a situation where there is a period when
|
34285
|
-
* is out of
|
35233
|
+
* If you have an input that uses `ng-model-options` to set up debounced updates or updates that
|
35234
|
+
* depend on special events such as blur, you can have a situation where there is a period when
|
35235
|
+
* the `$viewValue` is out of sync with the ngModel's `$modelValue`.
|
35236
|
+
*
|
35237
|
+
* In this case, you can use `$rollbackViewValue()` to manually cancel the debounced / future update
|
35238
|
+
* and reset the input to the last committed view value.
|
34286
35239
|
*
|
34287
|
-
*
|
35240
|
+
* It is also possible that you run into difficulties if you try to update the ngModel's `$modelValue`
|
34288
35241
|
* programmatically before these debounced/future events have resolved/occurred, because Angular's
|
34289
35242
|
* dirty checking mechanism is not able to tell whether the model has actually changed or not.
|
34290
35243
|
*
|
@@ -34297,39 +35250,63 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
34297
35250
|
* angular.module('cancel-update-example', [])
|
34298
35251
|
*
|
34299
35252
|
* .controller('CancelUpdateController', ['$scope', function($scope) {
|
34300
|
-
* $scope.
|
34301
|
-
*
|
34302
|
-
*
|
34303
|
-
* $scope.myValue = '';
|
34304
|
-
* }
|
34305
|
-
* };
|
34306
|
-
* $scope.resetWithoutCancel = function(e) {
|
35253
|
+
* $scope.model = {};
|
35254
|
+
*
|
35255
|
+
* $scope.setEmpty = function(e, value, rollback) {
|
34307
35256
|
* if (e.keyCode == 27) {
|
34308
|
-
*
|
35257
|
+
* e.preventDefault();
|
35258
|
+
* if (rollback) {
|
35259
|
+
* $scope.myForm[value].$rollbackViewValue();
|
35260
|
+
* }
|
35261
|
+
* $scope.model[value] = '';
|
34309
35262
|
* }
|
34310
35263
|
* };
|
34311
35264
|
* }]);
|
34312
35265
|
* </file>
|
34313
35266
|
* <file name="index.html">
|
34314
35267
|
* <div ng-controller="CancelUpdateController">
|
34315
|
-
*
|
34316
|
-
*
|
34317
|
-
*
|
34318
|
-
*
|
35268
|
+
* <p>Both of these inputs are only updated if they are blurred. Hitting escape should
|
35269
|
+
* empty them. Follow these steps and observe the difference:</p>
|
35270
|
+
* <ol>
|
35271
|
+
* <li>Type something in the input. You will see that the model is not yet updated</li>
|
35272
|
+
* <li>Press the Escape key.
|
35273
|
+
* <ol>
|
35274
|
+
* <li> In the first example, nothing happens, because the model is already '', and no
|
35275
|
+
* update is detected. If you blur the input, the model will be set to the current view.
|
35276
|
+
* </li>
|
35277
|
+
* <li> In the second example, the pending update is cancelled, and the input is set back
|
35278
|
+
* to the last committed view value (''). Blurring the input does nothing.
|
35279
|
+
* </li>
|
35280
|
+
* </ol>
|
35281
|
+
* </li>
|
35282
|
+
* </ol>
|
34319
35283
|
*
|
34320
35284
|
* <form name="myForm" ng-model-options="{ updateOn: 'blur' }">
|
34321
|
-
* <
|
34322
|
-
*
|
34323
|
-
*
|
34324
|
-
*
|
34325
|
-
*
|
34326
|
-
*
|
34327
|
-
*
|
34328
|
-
*
|
34329
|
-
*
|
35285
|
+
* <div>
|
35286
|
+
* <p id="inputDescription1">Without $rollbackViewValue():</p>
|
35287
|
+
* <input name="value1" aria-describedby="inputDescription1" ng-model="model.value1"
|
35288
|
+
* ng-keydown="setEmpty($event, 'value1')">
|
35289
|
+
* value1: "{{ model.value1 }}"
|
35290
|
+
* </div>
|
35291
|
+
*
|
35292
|
+
* <div>
|
35293
|
+
* <p id="inputDescription2">With $rollbackViewValue():</p>
|
35294
|
+
* <input name="value2" aria-describedby="inputDescription2" ng-model="model.value2"
|
35295
|
+
* ng-keydown="setEmpty($event, 'value2', true)">
|
35296
|
+
* value2: "{{ model.value2 }}"
|
35297
|
+
* </div>
|
34330
35298
|
* </form>
|
34331
35299
|
* </div>
|
34332
35300
|
* </file>
|
35301
|
+
<file name="style.css">
|
35302
|
+
div {
|
35303
|
+
display: table-cell;
|
35304
|
+
}
|
35305
|
+
div:nth-child(1) {
|
35306
|
+
padding-right: 30px;
|
35307
|
+
}
|
35308
|
+
|
35309
|
+
</file>
|
34333
35310
|
* </example>
|
34334
35311
|
*/
|
34335
35312
|
this.$rollbackViewValue = function() {
|
@@ -34443,7 +35420,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
34443
35420
|
forEach(ctrl.$asyncValidators, function(validator, name) {
|
34444
35421
|
var promise = validator(modelValue, viewValue);
|
34445
35422
|
if (!isPromiseLike(promise)) {
|
34446
|
-
throw ngModelMinErr(
|
35423
|
+
throw ngModelMinErr('nopromise',
|
34447
35424
|
"Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
|
34448
35425
|
}
|
34449
35426
|
setValidity(name, undefined);
|
@@ -34499,6 +35476,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
34499
35476
|
if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {
|
34500
35477
|
return;
|
34501
35478
|
}
|
35479
|
+
ctrl.$$updateEmptyClasses(viewValue);
|
34502
35480
|
ctrl.$$lastCommittedViewValue = viewValue;
|
34503
35481
|
|
34504
35482
|
// change to dirty
|
@@ -34597,7 +35575,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
34597
35575
|
* However, custom controls might also pass objects to this method. In this case, we should make
|
34598
35576
|
* a copy of the object before passing it to `$setViewValue`. This is because `ngModel` does not
|
34599
35577
|
* perform a deep watch of objects, it only looks for a change of identity. If you only change
|
34600
|
-
* the property of the object then ngModel will not
|
35578
|
+
* the property of the object then ngModel will not realize that the object has changed and
|
34601
35579
|
* will not invoke the `$parsers` and `$validators` pipelines. For this reason, you should
|
34602
35580
|
* not change properties of the copy once it has been passed to `$setViewValue`.
|
34603
35581
|
* Otherwise you may cause the model value on the scope to change incorrectly.
|
@@ -34681,6 +35659,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
34681
35659
|
viewValue = formatters[idx](viewValue);
|
34682
35660
|
}
|
34683
35661
|
if (ctrl.$viewValue !== viewValue) {
|
35662
|
+
ctrl.$$updateEmptyClasses(viewValue);
|
34684
35663
|
ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
|
34685
35664
|
ctrl.$render();
|
34686
35665
|
|
@@ -34711,7 +35690,8 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
34711
35690
|
* require.
|
34712
35691
|
* - Providing validation behavior (i.e. required, number, email, url).
|
34713
35692
|
* - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).
|
34714
|
-
* - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`,
|
35693
|
+
* - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`,
|
35694
|
+
* `ng-untouched`, `ng-empty`, `ng-not-empty`) including animations.
|
34715
35695
|
* - Registering the control with its parent {@link ng.directive:form form}.
|
34716
35696
|
*
|
34717
35697
|
* Note: `ngModel` will try to bind to the property given by evaluating the expression on the
|
@@ -34739,6 +35719,22 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
34739
35719
|
* - {@link ng.directive:select select}
|
34740
35720
|
* - {@link ng.directive:textarea textarea}
|
34741
35721
|
*
|
35722
|
+
* # Complex Models (objects or collections)
|
35723
|
+
*
|
35724
|
+
* By default, `ngModel` watches the model by reference, not value. This is important to know when
|
35725
|
+
* binding inputs to models that are objects (e.g. `Date`) or collections (e.g. arrays). If only properties of the
|
35726
|
+
* object or collection change, `ngModel` will not be notified and so the input will not be re-rendered.
|
35727
|
+
*
|
35728
|
+
* The model must be assigned an entirely new object or collection before a re-rendering will occur.
|
35729
|
+
*
|
35730
|
+
* Some directives have options that will cause them to use a custom `$watchCollection` on the model expression
|
35731
|
+
* - for example, `ngOptions` will do so when a `track by` clause is included in the comprehension expression or
|
35732
|
+
* if the select is given the `multiple` attribute.
|
35733
|
+
*
|
35734
|
+
* The `$watchCollection()` method only does a shallow comparison, meaning that changing properties deeper than the
|
35735
|
+
* first level of the object (or only changing the properties of an item in the collection if it's an array) will still
|
35736
|
+
* not trigger a re-rendering of the model.
|
35737
|
+
*
|
34742
35738
|
* # CSS classes
|
34743
35739
|
* The following CSS classes are added and removed on the associated input/select/textarea element
|
34744
35740
|
* depending on the validity of the model.
|
@@ -34752,13 +35748,16 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
34752
35748
|
* - `ng-touched`: the control has been blurred
|
34753
35749
|
* - `ng-untouched`: the control hasn't been blurred
|
34754
35750
|
* - `ng-pending`: any `$asyncValidators` are unfulfilled
|
35751
|
+
* - `ng-empty`: the view does not contain a value or the value is deemed "empty", as defined
|
35752
|
+
* by the {@link ngModel.NgModelController#$isEmpty} method
|
35753
|
+
* - `ng-not-empty`: the view contains a non-empty value
|
34755
35754
|
*
|
34756
35755
|
* Keep in mind that ngAnimate can detect each of these classes when added and removed.
|
34757
35756
|
*
|
34758
35757
|
* ## Animation Hooks
|
34759
35758
|
*
|
34760
35759
|
* Animations within models are triggered when any of the associated CSS classes are added and removed
|
34761
|
-
* on the input element which is attached to the model. These classes
|
35760
|
+
* on the input element which is attached to the model. These classes include: `.ng-pristine`, `.ng-dirty`,
|
34762
35761
|
* `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.
|
34763
35762
|
* The animations that are triggered within ngModel are similar to how they work in ngClass and
|
34764
35763
|
* animations can be hooked into using CSS transitions, keyframes as well as JS animations.
|
@@ -35651,14 +36650,10 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
35651
36650
|
var optionTemplate = document.createElement('option'),
|
35652
36651
|
optGroupTemplate = document.createElement('optgroup');
|
35653
36652
|
|
35654
|
-
|
35655
36653
|
function ngOptionsPostLink(scope, selectElement, attr, ctrls) {
|
35656
36654
|
|
35657
|
-
// if ngModel is not defined, we don't need to do anything
|
35658
|
-
var ngModelCtrl = ctrls[1];
|
35659
|
-
if (!ngModelCtrl) return;
|
35660
|
-
|
35661
36655
|
var selectCtrl = ctrls[0];
|
36656
|
+
var ngModelCtrl = ctrls[1];
|
35662
36657
|
var multiple = attr.multiple;
|
35663
36658
|
|
35664
36659
|
// The emptyOption allows the application developer to provide their own custom "empty"
|
@@ -35889,7 +36884,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
35889
36884
|
(current === emptyOption_ ||
|
35890
36885
|
current === unknownOption_ ||
|
35891
36886
|
current.nodeType === NODE_TYPE_COMMENT ||
|
35892
|
-
current.value === '')) {
|
36887
|
+
(nodeName_(current) === 'option' && current.value === ''))) {
|
35893
36888
|
current = current.nextSibling;
|
35894
36889
|
}
|
35895
36890
|
}
|
@@ -35918,7 +36913,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
35918
36913
|
var groupElement;
|
35919
36914
|
var optionElement;
|
35920
36915
|
|
35921
|
-
if (option.group) {
|
36916
|
+
if (isDefined(option.group)) {
|
35922
36917
|
|
35923
36918
|
// This option is to live in a group
|
35924
36919
|
// See if we have already created this group
|
@@ -35979,7 +36974,8 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
35979
36974
|
// Check to see if the value has changed due to the update to the options
|
35980
36975
|
if (!ngModelCtrl.$isEmpty(previousValue)) {
|
35981
36976
|
var nextValue = selectCtrl.readValue();
|
35982
|
-
|
36977
|
+
var isNotPrimitive = ngOptions.trackBy || multiple;
|
36978
|
+
if (isNotPrimitive ? !equals(previousValue, nextValue) : previousValue !== nextValue) {
|
35983
36979
|
ngModelCtrl.$setViewValue(nextValue);
|
35984
36980
|
ngModelCtrl.$render();
|
35985
36981
|
}
|
@@ -35991,7 +36987,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
35991
36987
|
return {
|
35992
36988
|
restrict: 'A',
|
35993
36989
|
terminal: true,
|
35994
|
-
require: ['select', '
|
36990
|
+
require: ['select', 'ngModel'],
|
35995
36991
|
link: {
|
35996
36992
|
pre: function ngOptionsPreLink(scope, selectElement, attr, ctrls) {
|
35997
36993
|
// Deactivate the SelectController.register method to prevent
|
@@ -36219,7 +37215,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
|
|
36219
37215
|
}
|
36220
37216
|
|
36221
37217
|
// If both `count` and `lastCount` are NaN, we don't need to re-register a watch.
|
36222
|
-
// In JS `NaN !== NaN`, so we have to
|
37218
|
+
// In JS `NaN !== NaN`, so we have to explicitly check.
|
36223
37219
|
if ((count !== lastCount) && !(countIsNaN && isNumber(lastCount) && isNaN(lastCount))) {
|
36224
37220
|
watchRemover();
|
36225
37221
|
var whenExpFn = whensExpFns[count];
|
@@ -36336,7 +37332,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
|
|
36336
37332
|
* by the identifier instead of the whole object. Should you reload your data later, `ngRepeat`
|
36337
37333
|
* will not have to rebuild the DOM elements for items it has already rendered, even if the
|
36338
37334
|
* JavaScript objects in the collection have been substituted for new ones. For large collections,
|
36339
|
-
* this
|
37335
|
+
* this significantly improves rendering performance. If you don't have a unique identifier,
|
36340
37336
|
* `track by $index` can also provide a performance boost.
|
36341
37337
|
* </div>
|
36342
37338
|
* ```html
|
@@ -36413,6 +37409,8 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
|
|
36413
37409
|
*
|
36414
37410
|
* **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered
|
36415
37411
|
*
|
37412
|
+
* See the example below for defining CSS animations with ngRepeat.
|
37413
|
+
*
|
36416
37414
|
* @element ANY
|
36417
37415
|
* @scope
|
36418
37416
|
* @priority 1000
|
@@ -36465,22 +37463,11 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
|
|
36465
37463
|
* For example: `item in items | filter : x | orderBy : order | limitTo : limit as results` .
|
36466
37464
|
*
|
36467
37465
|
* @example
|
36468
|
-
* This example
|
36469
|
-
*
|
36470
|
-
<example module="
|
37466
|
+
* This example uses `ngRepeat` to display a list of people. A filter is used to restrict the displayed
|
37467
|
+
* results by name. New (entering) and removed (leaving) items are animated.
|
37468
|
+
<example module="ngRepeat" name="ngRepeat" deps="angular-animate.js" animations="true">
|
36471
37469
|
<file name="index.html">
|
36472
|
-
<div ng-
|
36473
|
-
{name:'John', age:25, gender:'boy'},
|
36474
|
-
{name:'Jessie', age:30, gender:'girl'},
|
36475
|
-
{name:'Johanna', age:28, gender:'girl'},
|
36476
|
-
{name:'Joy', age:15, gender:'girl'},
|
36477
|
-
{name:'Mary', age:28, gender:'girl'},
|
36478
|
-
{name:'Peter', age:95, gender:'boy'},
|
36479
|
-
{name:'Sebastian', age:50, gender:'boy'},
|
36480
|
-
{name:'Erika', age:27, gender:'girl'},
|
36481
|
-
{name:'Patrick', age:40, gender:'boy'},
|
36482
|
-
{name:'Samantha', age:60, gender:'girl'}
|
36483
|
-
]">
|
37470
|
+
<div ng-controller="repeatController">
|
36484
37471
|
I have {{friends.length}} friends. They are:
|
36485
37472
|
<input type="search" ng-model="q" placeholder="filter friends..." aria-label="filter friends" />
|
36486
37473
|
<ul class="example-animate-container">
|
@@ -36493,6 +37480,22 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
|
|
36493
37480
|
</ul>
|
36494
37481
|
</div>
|
36495
37482
|
</file>
|
37483
|
+
<file name="script.js">
|
37484
|
+
angular.module('ngRepeat', ['ngAnimate']).controller('repeatController', function($scope) {
|
37485
|
+
$scope.friends = [
|
37486
|
+
{name:'John', age:25, gender:'boy'},
|
37487
|
+
{name:'Jessie', age:30, gender:'girl'},
|
37488
|
+
{name:'Johanna', age:28, gender:'girl'},
|
37489
|
+
{name:'Joy', age:15, gender:'girl'},
|
37490
|
+
{name:'Mary', age:28, gender:'girl'},
|
37491
|
+
{name:'Peter', age:95, gender:'boy'},
|
37492
|
+
{name:'Sebastian', age:50, gender:'boy'},
|
37493
|
+
{name:'Erika', age:27, gender:'girl'},
|
37494
|
+
{name:'Patrick', age:40, gender:'boy'},
|
37495
|
+
{name:'Samantha', age:60, gender:'girl'}
|
37496
|
+
];
|
37497
|
+
});
|
37498
|
+
</file>
|
36496
37499
|
<file name="animations.css">
|
36497
37500
|
.example-animate-container {
|
36498
37501
|
background:white;
|
@@ -36503,7 +37506,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
|
|
36503
37506
|
}
|
36504
37507
|
|
36505
37508
|
.animate-repeat {
|
36506
|
-
line-height:
|
37509
|
+
line-height:30px;
|
36507
37510
|
list-style:none;
|
36508
37511
|
box-sizing:border-box;
|
36509
37512
|
}
|
@@ -36525,7 +37528,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
|
|
36525
37528
|
.animate-repeat.ng-move.ng-move-active,
|
36526
37529
|
.animate-repeat.ng-enter.ng-enter-active {
|
36527
37530
|
opacity:1;
|
36528
|
-
max-height:
|
37531
|
+
max-height:30px;
|
36529
37532
|
}
|
36530
37533
|
</file>
|
36531
37534
|
<file name="protractor.js" type="protractor">
|
@@ -37382,67 +38385,186 @@ var ngSwitchDefaultDirective = ngDirective({
|
|
37382
38385
|
* @description
|
37383
38386
|
* Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.
|
37384
38387
|
*
|
37385
|
-
*
|
38388
|
+
* You can specify that you want to insert a named transclusion slot, instead of the default slot, by providing the slot name
|
38389
|
+
* as the value of the `ng-transclude` or `ng-transclude-slot` attribute.
|
38390
|
+
*
|
38391
|
+
* If the transcluded content is not empty (i.e. contains one or more DOM nodes, including whitespace text nodes), any existing
|
38392
|
+
* content of this element will be removed before the transcluded content is inserted.
|
38393
|
+
* If the transcluded content is empty, the existing content is left intact. This lets you provide fallback content in the case
|
38394
|
+
* that no transcluded content is provided.
|
37386
38395
|
*
|
37387
38396
|
* @element ANY
|
37388
38397
|
*
|
38398
|
+
* @param {string} ngTransclude|ngTranscludeSlot the name of the slot to insert at this point. If this is not provided, is empty
|
38399
|
+
* or its value is the same as the name of the attribute then the default slot is used.
|
38400
|
+
*
|
37389
38401
|
* @example
|
37390
|
-
|
37391
|
-
|
37392
|
-
|
37393
|
-
|
37394
|
-
|
37395
|
-
|
37396
|
-
|
37397
|
-
|
37398
|
-
|
37399
|
-
|
37400
|
-
|
37401
|
-
|
37402
|
-
'</div>'
|
37403
|
-
|
37404
|
-
|
37405
|
-
|
37406
|
-
|
37407
|
-
|
37408
|
-
|
37409
|
-
|
37410
|
-
|
37411
|
-
|
37412
|
-
|
37413
|
-
|
37414
|
-
|
37415
|
-
|
37416
|
-
|
37417
|
-
|
37418
|
-
|
37419
|
-
|
37420
|
-
|
37421
|
-
|
37422
|
-
|
37423
|
-
|
37424
|
-
|
37425
|
-
|
37426
|
-
|
37427
|
-
|
37428
|
-
|
38402
|
+
* ### Basic transclusion
|
38403
|
+
* This example demonstrates basic transclusion of content into a component directive.
|
38404
|
+
* <example name="simpleTranscludeExample" module="transcludeExample">
|
38405
|
+
* <file name="index.html">
|
38406
|
+
* <script>
|
38407
|
+
* angular.module('transcludeExample', [])
|
38408
|
+
* .directive('pane', function(){
|
38409
|
+
* return {
|
38410
|
+
* restrict: 'E',
|
38411
|
+
* transclude: true,
|
38412
|
+
* scope: { title:'@' },
|
38413
|
+
* template: '<div style="border: 1px solid black;">' +
|
38414
|
+
* '<div style="background-color: gray">{{title}}</div>' +
|
38415
|
+
* '<ng-transclude></ng-transclude>' +
|
38416
|
+
* '</div>'
|
38417
|
+
* };
|
38418
|
+
* })
|
38419
|
+
* .controller('ExampleController', ['$scope', function($scope) {
|
38420
|
+
* $scope.title = 'Lorem Ipsum';
|
38421
|
+
* $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
|
38422
|
+
* }]);
|
38423
|
+
* </script>
|
38424
|
+
* <div ng-controller="ExampleController">
|
38425
|
+
* <input ng-model="title" aria-label="title"> <br/>
|
38426
|
+
* <textarea ng-model="text" aria-label="text"></textarea> <br/>
|
38427
|
+
* <pane title="{{title}}">{{text}}</pane>
|
38428
|
+
* </div>
|
38429
|
+
* </file>
|
38430
|
+
* <file name="protractor.js" type="protractor">
|
38431
|
+
* it('should have transcluded', function() {
|
38432
|
+
* var titleElement = element(by.model('title'));
|
38433
|
+
* titleElement.clear();
|
38434
|
+
* titleElement.sendKeys('TITLE');
|
38435
|
+
* var textElement = element(by.model('text'));
|
38436
|
+
* textElement.clear();
|
38437
|
+
* textElement.sendKeys('TEXT');
|
38438
|
+
* expect(element(by.binding('title')).getText()).toEqual('TITLE');
|
38439
|
+
* expect(element(by.binding('text')).getText()).toEqual('TEXT');
|
38440
|
+
* });
|
38441
|
+
* </file>
|
38442
|
+
* </example>
|
38443
|
+
*
|
38444
|
+
* @example
|
38445
|
+
* ### Transclude fallback content
|
38446
|
+
* This example shows how to use `NgTransclude` with fallback content, that
|
38447
|
+
* is displayed if no transcluded content is provided.
|
38448
|
+
*
|
38449
|
+
* <example module="transcludeFallbackContentExample">
|
38450
|
+
* <file name="index.html">
|
38451
|
+
* <script>
|
38452
|
+
* angular.module('transcludeFallbackContentExample', [])
|
38453
|
+
* .directive('myButton', function(){
|
38454
|
+
* return {
|
38455
|
+
* restrict: 'E',
|
38456
|
+
* transclude: true,
|
38457
|
+
* scope: true,
|
38458
|
+
* template: '<button style="cursor: pointer;">' +
|
38459
|
+
* '<ng-transclude>' +
|
38460
|
+
* '<b style="color: red;">Button1</b>' +
|
38461
|
+
* '</ng-transclude>' +
|
38462
|
+
* '</button>'
|
38463
|
+
* };
|
38464
|
+
* });
|
38465
|
+
* </script>
|
38466
|
+
* <!-- fallback button content -->
|
38467
|
+
* <my-button id="fallback"></my-button>
|
38468
|
+
* <!-- modified button content -->
|
38469
|
+
* <my-button id="modified">
|
38470
|
+
* <i style="color: green;">Button2</i>
|
38471
|
+
* </my-button>
|
38472
|
+
* </file>
|
38473
|
+
* <file name="protractor.js" type="protractor">
|
38474
|
+
* it('should have different transclude element content', function() {
|
38475
|
+
* expect(element(by.id('fallback')).getText()).toBe('Button1');
|
38476
|
+
* expect(element(by.id('modified')).getText()).toBe('Button2');
|
38477
|
+
* });
|
38478
|
+
* </file>
|
38479
|
+
* </example>
|
37429
38480
|
*
|
38481
|
+
* @example
|
38482
|
+
* ### Multi-slot transclusion
|
38483
|
+
* This example demonstrates using multi-slot transclusion in a component directive.
|
38484
|
+
* <example name="multiSlotTranscludeExample" module="multiSlotTranscludeExample">
|
38485
|
+
* <file name="index.html">
|
38486
|
+
* <style>
|
38487
|
+
* .title, .footer {
|
38488
|
+
* background-color: gray
|
38489
|
+
* }
|
38490
|
+
* </style>
|
38491
|
+
* <div ng-controller="ExampleController">
|
38492
|
+
* <input ng-model="title" aria-label="title"> <br/>
|
38493
|
+
* <textarea ng-model="text" aria-label="text"></textarea> <br/>
|
38494
|
+
* <pane>
|
38495
|
+
* <pane-title><a ng-href="{{link}}">{{title}}</a></pane-title>
|
38496
|
+
* <pane-body><p>{{text}}</p></pane-body>
|
38497
|
+
* </pane>
|
38498
|
+
* </div>
|
38499
|
+
* </file>
|
38500
|
+
* <file name="app.js">
|
38501
|
+
* angular.module('multiSlotTranscludeExample', [])
|
38502
|
+
* .directive('pane', function(){
|
38503
|
+
* return {
|
38504
|
+
* restrict: 'E',
|
38505
|
+
* transclude: {
|
38506
|
+
* 'title': '?paneTitle',
|
38507
|
+
* 'body': 'paneBody',
|
38508
|
+
* 'footer': '?paneFooter'
|
38509
|
+
* },
|
38510
|
+
* template: '<div style="border: 1px solid black;">' +
|
38511
|
+
* '<div class="title" ng-transclude="title">Fallback Title</div>' +
|
38512
|
+
* '<div ng-transclude="body"></div>' +
|
38513
|
+
* '<div class="footer" ng-transclude="footer">Fallback Footer</div>' +
|
38514
|
+
* '</div>'
|
38515
|
+
* };
|
38516
|
+
* })
|
38517
|
+
* .controller('ExampleController', ['$scope', function($scope) {
|
38518
|
+
* $scope.title = 'Lorem Ipsum';
|
38519
|
+
* $scope.link = "https://google.com";
|
38520
|
+
* $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
|
38521
|
+
* }]);
|
38522
|
+
* </file>
|
38523
|
+
* <file name="protractor.js" type="protractor">
|
38524
|
+
* it('should have transcluded the title and the body', function() {
|
38525
|
+
* var titleElement = element(by.model('title'));
|
38526
|
+
* titleElement.clear();
|
38527
|
+
* titleElement.sendKeys('TITLE');
|
38528
|
+
* var textElement = element(by.model('text'));
|
38529
|
+
* textElement.clear();
|
38530
|
+
* textElement.sendKeys('TEXT');
|
38531
|
+
* expect(element(by.css('.title')).getText()).toEqual('TITLE');
|
38532
|
+
* expect(element(by.binding('text')).getText()).toEqual('TEXT');
|
38533
|
+
* expect(element(by.css('.footer')).getText()).toEqual('Fallback Footer');
|
38534
|
+
* });
|
38535
|
+
* </file>
|
38536
|
+
* </example>
|
37430
38537
|
*/
|
38538
|
+
var ngTranscludeMinErr = minErr('ngTransclude');
|
37431
38539
|
var ngTranscludeDirective = ngDirective({
|
37432
38540
|
restrict: 'EAC',
|
37433
38541
|
link: function($scope, $element, $attrs, controller, $transclude) {
|
38542
|
+
|
38543
|
+
if ($attrs.ngTransclude === $attrs.$attr.ngTransclude) {
|
38544
|
+
// If the attribute is of the form: `ng-transclude="ng-transclude"`
|
38545
|
+
// then treat it like the default
|
38546
|
+
$attrs.ngTransclude = '';
|
38547
|
+
}
|
38548
|
+
|
38549
|
+
function ngTranscludeCloneAttachFn(clone) {
|
38550
|
+
if (clone.length) {
|
38551
|
+
$element.empty();
|
38552
|
+
$element.append(clone);
|
38553
|
+
}
|
38554
|
+
}
|
38555
|
+
|
37434
38556
|
if (!$transclude) {
|
37435
|
-
throw
|
38557
|
+
throw ngTranscludeMinErr('orphan',
|
37436
38558
|
'Illegal use of ngTransclude directive in the template! ' +
|
37437
38559
|
'No parent directive that requires a transclusion found. ' +
|
37438
38560
|
'Element: {0}',
|
37439
38561
|
startingTag($element));
|
37440
38562
|
}
|
37441
38563
|
|
37442
|
-
|
37443
|
-
|
37444
|
-
|
37445
|
-
|
38564
|
+
// If there is no slot name defined or the slot name is not optional
|
38565
|
+
// then transclude the slot
|
38566
|
+
var slotName = $attrs.ngTransclude || $attrs.ngTranscludeSlot;
|
38567
|
+
$transclude(ngTranscludeCloneAttachFn, null, slotName);
|
37446
38568
|
}
|
37447
38569
|
});
|
37448
38570
|
|
@@ -37574,6 +38696,9 @@ var SelectController =
|
|
37574
38696
|
|
37575
38697
|
// Tell the select control that an option, with the given value, has been added
|
37576
38698
|
self.addOption = function(value, element) {
|
38699
|
+
// Skip comment nodes, as they only pollute the `optionsMap`
|
38700
|
+
if (element[0].nodeType === NODE_TYPE_COMMENT) return;
|
38701
|
+
|
37577
38702
|
assertNotHasOwnProperty(value, '"option value"');
|
37578
38703
|
if (value === '') {
|
37579
38704
|
self.emptyOption = element;
|
@@ -37648,7 +38773,7 @@ var SelectController =
|
|
37648
38773
|
*
|
37649
38774
|
* The `select` directive is used together with {@link ngModel `ngModel`} to provide data-binding
|
37650
38775
|
* between the scope and the `<select>` control (including setting default values).
|
37651
|
-
*
|
38776
|
+
* It also handles dynamic `<option>` elements, which can be added using the {@link ngRepeat `ngRepeat}` or
|
37652
38777
|
* {@link ngOptions `ngOptions`} directives.
|
37653
38778
|
*
|
37654
38779
|
* When an item in the `<select>` menu is selected, the value of the selected option will be bound
|
@@ -37658,7 +38783,7 @@ var SelectController =
|
|
37658
38783
|
*
|
37659
38784
|
* <div class="alert alert-warning">
|
37660
38785
|
* Note that the value of a `select` directive used without `ngOptions` is always a string.
|
37661
|
-
* When the model needs to be bound to a non-string value, you must either
|
38786
|
+
* When the model needs to be bound to a non-string value, you must either explicitly convert it
|
37662
38787
|
* using a directive (see example below) or use `ngOptions` to specify the set of options.
|
37663
38788
|
* This is because an option element can only be bound to string values at present.
|
37664
38789
|
* </div>
|
@@ -37850,7 +38975,8 @@ var selectDirective = function() {
|
|
37850
38975
|
controller: SelectController,
|
37851
38976
|
priority: 1,
|
37852
38977
|
link: {
|
37853
|
-
pre: selectPreLink
|
38978
|
+
pre: selectPreLink,
|
38979
|
+
post: selectPostLink
|
37854
38980
|
}
|
37855
38981
|
};
|
37856
38982
|
|
@@ -37864,13 +38990,6 @@ var selectDirective = function() {
|
|
37864
38990
|
|
37865
38991
|
selectCtrl.ngModelCtrl = ngModelCtrl;
|
37866
38992
|
|
37867
|
-
// We delegate rendering to the `writeValue` method, which can be changed
|
37868
|
-
// if the select can have multiple selected values or if the options are being
|
37869
|
-
// generated by `ngOptions`
|
37870
|
-
ngModelCtrl.$render = function() {
|
37871
|
-
selectCtrl.writeValue(ngModelCtrl.$viewValue);
|
37872
|
-
};
|
37873
|
-
|
37874
38993
|
// When the selected item(s) changes we delegate getting the value of the select control
|
37875
38994
|
// to the `readValue` method, which can be changed if the select can have multiple
|
37876
38995
|
// selected values or if the options are being generated by `ngOptions`
|
@@ -37924,6 +39043,23 @@ var selectDirective = function() {
|
|
37924
39043
|
|
37925
39044
|
}
|
37926
39045
|
}
|
39046
|
+
|
39047
|
+
function selectPostLink(scope, element, attrs, ctrls) {
|
39048
|
+
// if ngModel is not defined, we don't need to do anything
|
39049
|
+
var ngModelCtrl = ctrls[1];
|
39050
|
+
if (!ngModelCtrl) return;
|
39051
|
+
|
39052
|
+
var selectCtrl = ctrls[0];
|
39053
|
+
|
39054
|
+
// We delegate rendering to the `writeValue` method, which can be changed
|
39055
|
+
// if the select can have multiple selected values or if the options are being
|
39056
|
+
// generated by `ngOptions`.
|
39057
|
+
// This must be done in the postLink fn to prevent $render to be called before
|
39058
|
+
// all nodes have been linked correctly.
|
39059
|
+
ngModelCtrl.$render = function() {
|
39060
|
+
selectCtrl.writeValue(ngModelCtrl.$viewValue);
|
39061
|
+
};
|
39062
|
+
}
|
37927
39063
|
};
|
37928
39064
|
|
37929
39065
|
|
@@ -37935,7 +39071,6 @@ var optionDirective = ['$interpolate', function($interpolate) {
|
|
37935
39071
|
restrict: 'E',
|
37936
39072
|
priority: 100,
|
37937
39073
|
compile: function(element, attr) {
|
37938
|
-
|
37939
39074
|
if (isDefined(attr.value)) {
|
37940
39075
|
// If the value attribute is defined, check if it contains an interpolation
|
37941
39076
|
var interpolateValueFn = $interpolate(attr.value, true);
|
@@ -37949,7 +39084,6 @@ var optionDirective = ['$interpolate', function($interpolate) {
|
|
37949
39084
|
}
|
37950
39085
|
|
37951
39086
|
return function(scope, element, attr) {
|
37952
|
-
|
37953
39087
|
// This is an optimization over using ^^ since we don't want to have to search
|
37954
39088
|
// all the way to the root of the DOM for every single option element
|
37955
39089
|
var selectCtrlName = '$selectController',
|
@@ -37970,6 +39104,64 @@ var styleDirective = valueFn({
|
|
37970
39104
|
terminal: false
|
37971
39105
|
});
|
37972
39106
|
|
39107
|
+
/**
|
39108
|
+
* @ngdoc directive
|
39109
|
+
* @name ngRequired
|
39110
|
+
*
|
39111
|
+
* @description
|
39112
|
+
*
|
39113
|
+
* ngRequired adds the required {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
|
39114
|
+
* It is most often used for {@link input `input`} and {@link select `select`} controls, but can also be
|
39115
|
+
* applied to custom controls.
|
39116
|
+
*
|
39117
|
+
* The directive sets the `required` attribute on the element if the Angular expression inside
|
39118
|
+
* `ngRequired` evaluates to true. A special directive for setting `required` is necessary because we
|
39119
|
+
* cannot use interpolation inside `required`. See the {@link guide/interpolation interpolation guide}
|
39120
|
+
* for more info.
|
39121
|
+
*
|
39122
|
+
* The validator will set the `required` error key to true if the `required` attribute is set and
|
39123
|
+
* calling {@link ngModel.NgModelController#$isEmpty `NgModelController.$isEmpty`} with the
|
39124
|
+
* {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} returns `true`. For example, the
|
39125
|
+
* `$isEmpty()` implementation for `input[text]` checks the length of the `$viewValue`. When developing
|
39126
|
+
* custom controls, `$isEmpty()` can be overwritten to account for a $viewValue that is not string-based.
|
39127
|
+
*
|
39128
|
+
* @example
|
39129
|
+
* <example name="ngRequiredDirective" module="ngRequiredExample">
|
39130
|
+
* <file name="index.html">
|
39131
|
+
* <script>
|
39132
|
+
* angular.module('ngRequiredExample', [])
|
39133
|
+
* .controller('ExampleController', ['$scope', function($scope) {
|
39134
|
+
* $scope.required = true;
|
39135
|
+
* }]);
|
39136
|
+
* </script>
|
39137
|
+
* <div ng-controller="ExampleController">
|
39138
|
+
* <form name="form">
|
39139
|
+
* <label for="required">Toggle required: </label>
|
39140
|
+
* <input type="checkbox" ng-model="required" id="required" />
|
39141
|
+
* <br>
|
39142
|
+
* <label for="input">This input must be filled if `required` is true: </label>
|
39143
|
+
* <input type="text" ng-model="model" id="input" name="input" ng-required="required" /><br>
|
39144
|
+
* <hr>
|
39145
|
+
* required error set? = <code>{{form.input.$error.required}}</code><br>
|
39146
|
+
* model = <code>{{model}}</code>
|
39147
|
+
* </form>
|
39148
|
+
* </div>
|
39149
|
+
* </file>
|
39150
|
+
* <file name="protractor.js" type="protractor">
|
39151
|
+
var required = element(by.binding('form.input.$error.required'));
|
39152
|
+
var model = element(by.binding('model'));
|
39153
|
+
var input = element(by.id('input'));
|
39154
|
+
|
39155
|
+
it('should set the required error', function() {
|
39156
|
+
expect(required.getText()).toContain('true');
|
39157
|
+
|
39158
|
+
input.sendKeys('123');
|
39159
|
+
expect(required.getText()).not.toContain('true');
|
39160
|
+
expect(model.getText()).toContain('123');
|
39161
|
+
});
|
39162
|
+
* </file>
|
39163
|
+
* </example>
|
39164
|
+
*/
|
37973
39165
|
var requiredDirective = function() {
|
37974
39166
|
return {
|
37975
39167
|
restrict: 'A',
|
@@ -37989,7 +39181,81 @@ var requiredDirective = function() {
|
|
37989
39181
|
};
|
37990
39182
|
};
|
37991
39183
|
|
39184
|
+
/**
|
39185
|
+
* @ngdoc directive
|
39186
|
+
* @name ngPattern
|
39187
|
+
*
|
39188
|
+
* @description
|
39189
|
+
*
|
39190
|
+
* ngPattern adds the pattern {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
|
39191
|
+
* It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.
|
39192
|
+
*
|
39193
|
+
* The validator sets the `pattern` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}
|
39194
|
+
* does not match a RegExp which is obtained by evaluating the Angular expression given in the
|
39195
|
+
* `ngPattern` attribute value:
|
39196
|
+
* * If the expression evaluates to a RegExp object, then this is used directly.
|
39197
|
+
* * If the expression evaluates to a string, then it will be converted to a RegExp after wrapping it
|
39198
|
+
* in `^` and `$` characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
|
39199
|
+
*
|
39200
|
+
* <div class="alert alert-info">
|
39201
|
+
* **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
|
39202
|
+
* start at the index of the last search's match, thus not taking the whole input value into
|
39203
|
+
* account.
|
39204
|
+
* </div>
|
39205
|
+
*
|
39206
|
+
* <div class="alert alert-info">
|
39207
|
+
* **Note:** This directive is also added when the plain `pattern` attribute is used, with two
|
39208
|
+
* differences:
|
39209
|
+
* <ol>
|
39210
|
+
* <li>
|
39211
|
+
* `ngPattern` does not set the `pattern` attribute and therefore HTML5 constraint validation is
|
39212
|
+
* not available.
|
39213
|
+
* </li>
|
39214
|
+
* <li>
|
39215
|
+
* The `ngPattern` attribute must be an expression, while the `pattern` value must be
|
39216
|
+
* interpolated.
|
39217
|
+
* </li>
|
39218
|
+
* </ol>
|
39219
|
+
* </div>
|
39220
|
+
*
|
39221
|
+
* @example
|
39222
|
+
* <example name="ngPatternDirective" module="ngPatternExample">
|
39223
|
+
* <file name="index.html">
|
39224
|
+
* <script>
|
39225
|
+
* angular.module('ngPatternExample', [])
|
39226
|
+
* .controller('ExampleController', ['$scope', function($scope) {
|
39227
|
+
* $scope.regex = '\\d+';
|
39228
|
+
* }]);
|
39229
|
+
* </script>
|
39230
|
+
* <div ng-controller="ExampleController">
|
39231
|
+
* <form name="form">
|
39232
|
+
* <label for="regex">Set a pattern (regex string): </label>
|
39233
|
+
* <input type="text" ng-model="regex" id="regex" />
|
39234
|
+
* <br>
|
39235
|
+
* <label for="input">This input is restricted by the current pattern: </label>
|
39236
|
+
* <input type="text" ng-model="model" id="input" name="input" ng-pattern="regex" /><br>
|
39237
|
+
* <hr>
|
39238
|
+
* input valid? = <code>{{form.input.$valid}}</code><br>
|
39239
|
+
* model = <code>{{model}}</code>
|
39240
|
+
* </form>
|
39241
|
+
* </div>
|
39242
|
+
* </file>
|
39243
|
+
* <file name="protractor.js" type="protractor">
|
39244
|
+
var model = element(by.binding('model'));
|
39245
|
+
var input = element(by.id('input'));
|
39246
|
+
|
39247
|
+
it('should validate the input with the default pattern', function() {
|
39248
|
+
input.sendKeys('aaa');
|
39249
|
+
expect(model.getText()).not.toContain('aaa');
|
37992
39250
|
|
39251
|
+
input.clear().then(function() {
|
39252
|
+
input.sendKeys('123');
|
39253
|
+
expect(model.getText()).toContain('123');
|
39254
|
+
});
|
39255
|
+
});
|
39256
|
+
* </file>
|
39257
|
+
* </example>
|
39258
|
+
*/
|
37993
39259
|
var patternDirective = function() {
|
37994
39260
|
return {
|
37995
39261
|
restrict: 'A',
|
@@ -38021,7 +39287,72 @@ var patternDirective = function() {
|
|
38021
39287
|
};
|
38022
39288
|
};
|
38023
39289
|
|
39290
|
+
/**
|
39291
|
+
* @ngdoc directive
|
39292
|
+
* @name ngMaxlength
|
39293
|
+
*
|
39294
|
+
* @description
|
39295
|
+
*
|
39296
|
+
* ngMaxlength adds the maxlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
|
39297
|
+
* It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.
|
39298
|
+
*
|
39299
|
+
* The validator sets the `maxlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}
|
39300
|
+
* is longer than the integer obtained by evaluating the Angular expression given in the
|
39301
|
+
* `ngMaxlength` attribute value.
|
39302
|
+
*
|
39303
|
+
* <div class="alert alert-info">
|
39304
|
+
* **Note:** This directive is also added when the plain `maxlength` attribute is used, with two
|
39305
|
+
* differences:
|
39306
|
+
* <ol>
|
39307
|
+
* <li>
|
39308
|
+
* `ngMaxlength` does not set the `maxlength` attribute and therefore HTML5 constraint
|
39309
|
+
* validation is not available.
|
39310
|
+
* </li>
|
39311
|
+
* <li>
|
39312
|
+
* The `ngMaxlength` attribute must be an expression, while the `maxlength` value must be
|
39313
|
+
* interpolated.
|
39314
|
+
* </li>
|
39315
|
+
* </ol>
|
39316
|
+
* </div>
|
39317
|
+
*
|
39318
|
+
* @example
|
39319
|
+
* <example name="ngMaxlengthDirective" module="ngMaxlengthExample">
|
39320
|
+
* <file name="index.html">
|
39321
|
+
* <script>
|
39322
|
+
* angular.module('ngMaxlengthExample', [])
|
39323
|
+
* .controller('ExampleController', ['$scope', function($scope) {
|
39324
|
+
* $scope.maxlength = 5;
|
39325
|
+
* }]);
|
39326
|
+
* </script>
|
39327
|
+
* <div ng-controller="ExampleController">
|
39328
|
+
* <form name="form">
|
39329
|
+
* <label for="maxlength">Set a maxlength: </label>
|
39330
|
+
* <input type="number" ng-model="maxlength" id="maxlength" />
|
39331
|
+
* <br>
|
39332
|
+
* <label for="input">This input is restricted by the current maxlength: </label>
|
39333
|
+
* <input type="text" ng-model="model" id="input" name="input" ng-maxlength="maxlength" /><br>
|
39334
|
+
* <hr>
|
39335
|
+
* input valid? = <code>{{form.input.$valid}}</code><br>
|
39336
|
+
* model = <code>{{model}}</code>
|
39337
|
+
* </form>
|
39338
|
+
* </div>
|
39339
|
+
* </file>
|
39340
|
+
* <file name="protractor.js" type="protractor">
|
39341
|
+
var model = element(by.binding('model'));
|
39342
|
+
var input = element(by.id('input'));
|
39343
|
+
|
39344
|
+
it('should validate the input with the default maxlength', function() {
|
39345
|
+
input.sendKeys('abcdef');
|
39346
|
+
expect(model.getText()).not.toContain('abcdef');
|
38024
39347
|
|
39348
|
+
input.clear().then(function() {
|
39349
|
+
input.sendKeys('abcde');
|
39350
|
+
expect(model.getText()).toContain('abcde');
|
39351
|
+
});
|
39352
|
+
});
|
39353
|
+
* </file>
|
39354
|
+
* </example>
|
39355
|
+
*/
|
38025
39356
|
var maxlengthDirective = function() {
|
38026
39357
|
return {
|
38027
39358
|
restrict: 'A',
|
@@ -38042,6 +39373,70 @@ var maxlengthDirective = function() {
|
|
38042
39373
|
};
|
38043
39374
|
};
|
38044
39375
|
|
39376
|
+
/**
|
39377
|
+
* @ngdoc directive
|
39378
|
+
* @name ngMinlength
|
39379
|
+
*
|
39380
|
+
* @description
|
39381
|
+
*
|
39382
|
+
* ngMinlength adds the minlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
|
39383
|
+
* It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.
|
39384
|
+
*
|
39385
|
+
* The validator sets the `minlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}
|
39386
|
+
* is shorter than the integer obtained by evaluating the Angular expression given in the
|
39387
|
+
* `ngMinlength` attribute value.
|
39388
|
+
*
|
39389
|
+
* <div class="alert alert-info">
|
39390
|
+
* **Note:** This directive is also added when the plain `minlength` attribute is used, with two
|
39391
|
+
* differences:
|
39392
|
+
* <ol>
|
39393
|
+
* <li>
|
39394
|
+
* `ngMinlength` does not set the `minlength` attribute and therefore HTML5 constraint
|
39395
|
+
* validation is not available.
|
39396
|
+
* </li>
|
39397
|
+
* <li>
|
39398
|
+
* The `ngMinlength` value must be an expression, while the `minlength` value must be
|
39399
|
+
* interpolated.
|
39400
|
+
* </li>
|
39401
|
+
* </ol>
|
39402
|
+
* </div>
|
39403
|
+
*
|
39404
|
+
* @example
|
39405
|
+
* <example name="ngMinlengthDirective" module="ngMinlengthExample">
|
39406
|
+
* <file name="index.html">
|
39407
|
+
* <script>
|
39408
|
+
* angular.module('ngMinlengthExample', [])
|
39409
|
+
* .controller('ExampleController', ['$scope', function($scope) {
|
39410
|
+
* $scope.minlength = 3;
|
39411
|
+
* }]);
|
39412
|
+
* </script>
|
39413
|
+
* <div ng-controller="ExampleController">
|
39414
|
+
* <form name="form">
|
39415
|
+
* <label for="minlength">Set a minlength: </label>
|
39416
|
+
* <input type="number" ng-model="minlength" id="minlength" />
|
39417
|
+
* <br>
|
39418
|
+
* <label for="input">This input is restricted by the current minlength: </label>
|
39419
|
+
* <input type="text" ng-model="model" id="input" name="input" ng-minlength="minlength" /><br>
|
39420
|
+
* <hr>
|
39421
|
+
* input valid? = <code>{{form.input.$valid}}</code><br>
|
39422
|
+
* model = <code>{{model}}</code>
|
39423
|
+
* </form>
|
39424
|
+
* </div>
|
39425
|
+
* </file>
|
39426
|
+
* <file name="protractor.js" type="protractor">
|
39427
|
+
var model = element(by.binding('model'));
|
39428
|
+
var input = element(by.id('input'));
|
39429
|
+
|
39430
|
+
it('should validate the input with the default minlength', function() {
|
39431
|
+
input.sendKeys('ab');
|
39432
|
+
expect(model.getText()).not.toContain('ab');
|
39433
|
+
|
39434
|
+
input.sendKeys('abc');
|
39435
|
+
expect(model.getText()).toContain('abc');
|
39436
|
+
});
|
39437
|
+
* </file>
|
39438
|
+
* </example>
|
39439
|
+
*/
|
38045
39440
|
var minlengthDirective = function() {
|
38046
39441
|
return {
|
38047
39442
|
restrict: 'A',
|
@@ -38154,6 +39549,20 @@ $provide.value("$locale", {
|
|
38154
39549
|
"Nov",
|
38155
39550
|
"Dec"
|
38156
39551
|
],
|
39552
|
+
"STANDALONEMONTH": [
|
39553
|
+
"January",
|
39554
|
+
"February",
|
39555
|
+
"March",
|
39556
|
+
"April",
|
39557
|
+
"May",
|
39558
|
+
"June",
|
39559
|
+
"July",
|
39560
|
+
"August",
|
39561
|
+
"September",
|
39562
|
+
"October",
|
39563
|
+
"November",
|
39564
|
+
"December"
|
39565
|
+
],
|
38157
39566
|
"WEEKENDRANGE": [
|
38158
39567
|
5,
|
38159
39568
|
6
|
@@ -38197,6 +39606,7 @@ $provide.value("$locale", {
|
|
38197
39606
|
]
|
38198
39607
|
},
|
38199
39608
|
"id": "en-us",
|
39609
|
+
"localeID": "en_US",
|
38200
39610
|
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
|
38201
39611
|
});
|
38202
39612
|
}]);
|