angularjs-rails 1.4.8 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/angularjs-rails/version.rb +2 -2
- data/vendor/assets/javascripts/angular-animate.js +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
|
}]);
|