angularjs-rails 1.4.4 → 1.4.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/angularjs-rails/version.rb +2 -2
- data/vendor/assets/javascripts/angular-animate.js +266 -123
- data/vendor/assets/javascripts/angular-aria.js +40 -36
- data/vendor/assets/javascripts/angular-cookies.js +2 -2
- data/vendor/assets/javascripts/angular-loader.js +2 -2
- data/vendor/assets/javascripts/angular-message-format.js +1 -1
- data/vendor/assets/javascripts/angular-messages.js +9 -2
- data/vendor/assets/javascripts/angular-mocks.js +62 -25
- data/vendor/assets/javascripts/angular-resource.js +10 -4
- data/vendor/assets/javascripts/angular-route.js +1 -2
- data/vendor/assets/javascripts/angular-sanitize.js +1 -1
- data/vendor/assets/javascripts/angular-scenario.js +625 -325
- data/vendor/assets/javascripts/angular-touch.js +1 -1
- data/vendor/assets/javascripts/angular.js +624 -324
- data/vendor/assets/javascripts/unstable/angular2.js +13370 -14106
- metadata +2 -2
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.4.
|
2
|
+
* @license AngularJS v1.4.7
|
3
3
|
* (c) 2010-2015 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -57,7 +57,7 @@ function minErr(module, ErrorConstructor) {
|
|
57
57
|
return match;
|
58
58
|
});
|
59
59
|
|
60
|
-
message += '\nhttp://errors.angularjs.org/1.4.
|
60
|
+
message += '\nhttp://errors.angularjs.org/1.4.7/' +
|
61
61
|
(module ? module + '/' : '') + code;
|
62
62
|
|
63
63
|
for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
|
@@ -894,6 +894,8 @@ function copy(source, destination, stackSource, stackDest) {
|
|
894
894
|
} else if (isRegExp(source)) {
|
895
895
|
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
|
896
896
|
destination.lastIndex = source.lastIndex;
|
897
|
+
} else if (isFunction(source.cloneNode)) {
|
898
|
+
destination = source.cloneNode(true);
|
897
899
|
} else {
|
898
900
|
var emptyObject = Object.create(getPrototypeOf(source));
|
899
901
|
return copy(source, emptyObject, stackSource, stackDest);
|
@@ -1044,7 +1046,7 @@ function equals(o1, o2) {
|
|
1044
1046
|
for (key in o2) {
|
1045
1047
|
if (!(key in keySet) &&
|
1046
1048
|
key.charAt(0) !== '$' &&
|
1047
|
-
o2[key]
|
1049
|
+
isDefined(o2[key]) &&
|
1048
1050
|
!isFunction(o2[key])) return false;
|
1049
1051
|
}
|
1050
1052
|
return true;
|
@@ -1740,10 +1742,9 @@ function bindJQuery() {
|
|
1740
1742
|
|
1741
1743
|
// bind to jQuery if present;
|
1742
1744
|
var jqName = jq();
|
1743
|
-
jQuery = window.jQuery
|
1744
|
-
|
1745
|
-
|
1746
|
-
}
|
1745
|
+
jQuery = isUndefined(jqName) ? window.jQuery : // use jQuery (if present)
|
1746
|
+
!jqName ? undefined : // use jqLite
|
1747
|
+
window[jqName]; // use jQuery specified by `ngJq`
|
1747
1748
|
|
1748
1749
|
// Use jQuery if it exists with proper functionality, otherwise default to us.
|
1749
1750
|
// Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
|
@@ -1848,22 +1849,24 @@ function getter(obj, path, bindFnToScope) {
|
|
1848
1849
|
/**
|
1849
1850
|
* Return the DOM siblings between the first and last node in the given array.
|
1850
1851
|
* @param {Array} array like object
|
1851
|
-
* @returns {
|
1852
|
+
* @returns {Array} the inputted object or a jqLite collection containing the nodes
|
1852
1853
|
*/
|
1853
1854
|
function getBlockNodes(nodes) {
|
1854
|
-
// TODO(perf):
|
1855
|
-
// collection, otherwise update the original collection.
|
1855
|
+
// TODO(perf): update `nodes` instead of creating a new object?
|
1856
1856
|
var node = nodes[0];
|
1857
1857
|
var endNode = nodes[nodes.length - 1];
|
1858
|
-
var blockNodes
|
1858
|
+
var blockNodes;
|
1859
1859
|
|
1860
|
-
|
1861
|
-
|
1862
|
-
|
1863
|
-
|
1864
|
-
|
1860
|
+
for (var i = 1; node !== endNode && (node = node.nextSibling); i++) {
|
1861
|
+
if (blockNodes || nodes[i] !== node) {
|
1862
|
+
if (!blockNodes) {
|
1863
|
+
blockNodes = jqLite(slice.call(nodes, 0, i));
|
1864
|
+
}
|
1865
|
+
blockNodes.push(node);
|
1866
|
+
}
|
1867
|
+
}
|
1865
1868
|
|
1866
|
-
return
|
1869
|
+
return blockNodes || nodes;
|
1867
1870
|
}
|
1868
1871
|
|
1869
1872
|
|
@@ -2247,7 +2250,7 @@ function serializeObject(obj) {
|
|
2247
2250
|
val = toJsonReplacer(key, val);
|
2248
2251
|
if (isObject(val)) {
|
2249
2252
|
|
2250
|
-
if (seen.indexOf(val) >= 0) return '
|
2253
|
+
if (seen.indexOf(val) >= 0) return '...';
|
2251
2254
|
|
2252
2255
|
seen.push(val);
|
2253
2256
|
}
|
@@ -2258,7 +2261,7 @@ function serializeObject(obj) {
|
|
2258
2261
|
function toDebugString(obj) {
|
2259
2262
|
if (typeof obj === 'function') {
|
2260
2263
|
return obj.toString().replace(/ \{[\s\S]*$/, '');
|
2261
|
-
} else if (
|
2264
|
+
} else if (isUndefined(obj)) {
|
2262
2265
|
return 'undefined';
|
2263
2266
|
} else if (typeof obj !== 'string') {
|
2264
2267
|
return serializeObject(obj);
|
@@ -2338,6 +2341,7 @@ function toDebugString(obj) {
|
|
2338
2341
|
$HttpParamSerializerProvider,
|
2339
2342
|
$HttpParamSerializerJQLikeProvider,
|
2340
2343
|
$HttpBackendProvider,
|
2344
|
+
$xhrFactoryProvider,
|
2341
2345
|
$LocationProvider,
|
2342
2346
|
$LogProvider,
|
2343
2347
|
$ParseProvider,
|
@@ -2364,8 +2368,9 @@ function toDebugString(obj) {
|
|
2364
2368
|
* @name angular.version
|
2365
2369
|
* @module ng
|
2366
2370
|
* @description
|
2367
|
-
* An object that contains information about the current AngularJS version.
|
2368
|
-
*
|
2371
|
+
* An object that contains information about the current AngularJS version.
|
2372
|
+
*
|
2373
|
+
* This object has the following properties:
|
2369
2374
|
*
|
2370
2375
|
* - `full` – `{string}` – Full version string, such as "0.9.18".
|
2371
2376
|
* - `major` – `{number}` – Major version number, such as "0".
|
@@ -2374,11 +2379,11 @@ function toDebugString(obj) {
|
|
2374
2379
|
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
|
2375
2380
|
*/
|
2376
2381
|
var version = {
|
2377
|
-
full: '1.4.
|
2382
|
+
full: '1.4.7', // all of these placeholder strings will be replaced by grunt's
|
2378
2383
|
major: 1, // package task
|
2379
2384
|
minor: 4,
|
2380
|
-
dot:
|
2381
|
-
codeName: '
|
2385
|
+
dot: 7,
|
2386
|
+
codeName: 'dark-luminescence'
|
2382
2387
|
};
|
2383
2388
|
|
2384
2389
|
|
@@ -2495,6 +2500,7 @@ function publishExternalAPI(angular) {
|
|
2495
2500
|
$httpParamSerializer: $HttpParamSerializerProvider,
|
2496
2501
|
$httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider,
|
2497
2502
|
$httpBackend: $HttpBackendProvider,
|
2503
|
+
$xhrFactory: $xhrFactoryProvider,
|
2498
2504
|
$location: $LocationProvider,
|
2499
2505
|
$log: $LogProvider,
|
2500
2506
|
$parse: $ParseProvider,
|
@@ -2583,7 +2589,7 @@ function publishExternalAPI(angular) {
|
|
2583
2589
|
* - [`html()`](http://api.jquery.com/html/)
|
2584
2590
|
* - [`next()`](http://api.jquery.com/next/) - Does not support selectors
|
2585
2591
|
* - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
|
2586
|
-
* - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or
|
2592
|
+
* - [`off()`](http://api.jquery.com/off/) - Does not support namespaces, selectors or event object as parameter
|
2587
2593
|
* - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
|
2588
2594
|
* - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
|
2589
2595
|
* - [`prepend()`](http://api.jquery.com/prepend/)
|
@@ -2597,7 +2603,7 @@ function publishExternalAPI(angular) {
|
|
2597
2603
|
* - [`text()`](http://api.jquery.com/text/)
|
2598
2604
|
* - [`toggleClass()`](http://api.jquery.com/toggleClass/)
|
2599
2605
|
* - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
|
2600
|
-
* - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces
|
2606
|
+
* - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces or event object as parameter
|
2601
2607
|
* - [`val()`](http://api.jquery.com/val/)
|
2602
2608
|
* - [`wrap()`](http://api.jquery.com/wrap/)
|
2603
2609
|
*
|
@@ -2669,10 +2675,10 @@ function camelCase(name) {
|
|
2669
2675
|
replace(MOZ_HACK_REGEXP, 'Moz$1');
|
2670
2676
|
}
|
2671
2677
|
|
2672
|
-
var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
|
2678
|
+
var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/;
|
2673
2679
|
var HTML_REGEXP = /<|&#?\w+;/;
|
2674
|
-
var TAG_NAME_REGEXP = /<([\w
|
2675
|
-
var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w
|
2680
|
+
var TAG_NAME_REGEXP = /<([\w:-]+)/;
|
2681
|
+
var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi;
|
2676
2682
|
|
2677
2683
|
var wrapMap = {
|
2678
2684
|
'option': [1, '<select multiple="multiple">', '</select>'],
|
@@ -2968,7 +2974,7 @@ function jqLiteInheritedData(element, name, value) {
|
|
2968
2974
|
|
2969
2975
|
while (element) {
|
2970
2976
|
for (var i = 0, ii = names.length; i < ii; i++) {
|
2971
|
-
if ((value = jqLite.data(element, names[i]))
|
2977
|
+
if (isDefined(value = jqLite.data(element, names[i]))) return value;
|
2972
2978
|
}
|
2973
2979
|
|
2974
2980
|
// If dealing with a document fragment node with a host element, and no parent, use the host
|
@@ -3074,9 +3080,8 @@ function getBooleanAttrName(element, name) {
|
|
3074
3080
|
return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
|
3075
3081
|
}
|
3076
3082
|
|
3077
|
-
function getAliasedAttrName(
|
3078
|
-
|
3079
|
-
return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name];
|
3083
|
+
function getAliasedAttrName(name) {
|
3084
|
+
return ALIASED_ATTR[name];
|
3080
3085
|
}
|
3081
3086
|
|
3082
3087
|
forEach({
|
@@ -3213,7 +3218,7 @@ forEach({
|
|
3213
3218
|
// in a way that survives minification.
|
3214
3219
|
// jqLiteEmpty takes no arguments but is a setter.
|
3215
3220
|
if (fn !== jqLiteEmpty &&
|
3216
|
-
(((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2)
|
3221
|
+
(isUndefined((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2))) {
|
3217
3222
|
if (isObject(arg1)) {
|
3218
3223
|
|
3219
3224
|
// we are a write, but the object properties are the key/values
|
@@ -3234,7 +3239,7 @@ forEach({
|
|
3234
3239
|
// TODO: do we still need this?
|
3235
3240
|
var value = fn.$dv;
|
3236
3241
|
// Only if we have $dv do we iterate over all, otherwise it is just the first element.
|
3237
|
-
var jj = (value
|
3242
|
+
var jj = (isUndefined(value)) ? Math.min(nodeCount, 1) : nodeCount;
|
3238
3243
|
for (var j = 0; j < jj; j++) {
|
3239
3244
|
var nodeValue = fn(this[j], arg1, arg2);
|
3240
3245
|
value = value ? value + nodeValue : nodeValue;
|
@@ -4873,61 +4878,66 @@ var $$CoreAnimateQueueProvider = function() {
|
|
4873
4878
|
}
|
4874
4879
|
};
|
4875
4880
|
|
4876
|
-
function addRemoveClassesPostDigest(element, add, remove) {
|
4877
|
-
var classVal, data = postDigestQueue.get(element);
|
4878
4881
|
|
4879
|
-
|
4880
|
-
|
4881
|
-
|
4882
|
+
function updateData(data, classes, value) {
|
4883
|
+
var changed = false;
|
4884
|
+
if (classes) {
|
4885
|
+
classes = isString(classes) ? classes.split(' ') :
|
4886
|
+
isArray(classes) ? classes : [];
|
4887
|
+
forEach(classes, function(className) {
|
4888
|
+
if (className) {
|
4889
|
+
changed = true;
|
4890
|
+
data[className] = value;
|
4891
|
+
}
|
4892
|
+
});
|
4882
4893
|
}
|
4883
|
-
|
4884
|
-
|
4885
|
-
|
4886
|
-
|
4887
|
-
|
4888
|
-
|
4889
|
-
|
4890
|
-
|
4891
|
-
|
4892
|
-
|
4894
|
+
return changed;
|
4895
|
+
}
|
4896
|
+
|
4897
|
+
function handleCSSClassChanges() {
|
4898
|
+
forEach(postDigestElements, function(element) {
|
4899
|
+
var data = postDigestQueue.get(element);
|
4900
|
+
if (data) {
|
4901
|
+
var existing = splitClasses(element.attr('class'));
|
4902
|
+
var toAdd = '';
|
4903
|
+
var toRemove = '';
|
4904
|
+
forEach(data, function(status, className) {
|
4905
|
+
var hasClass = !!existing[className];
|
4906
|
+
if (status !== hasClass) {
|
4907
|
+
if (status) {
|
4908
|
+
toAdd += (toAdd.length ? ' ' : '') + className;
|
4909
|
+
} else {
|
4910
|
+
toRemove += (toRemove.length ? ' ' : '') + className;
|
4911
|
+
}
|
4893
4912
|
}
|
4894
4913
|
});
|
4914
|
+
|
4915
|
+
forEach(element, function(elm) {
|
4916
|
+
toAdd && jqLiteAddClass(elm, toAdd);
|
4917
|
+
toRemove && jqLiteRemoveClass(elm, toRemove);
|
4918
|
+
});
|
4919
|
+
postDigestQueue.remove(element);
|
4895
4920
|
}
|
4896
|
-
|
4897
|
-
|
4921
|
+
});
|
4922
|
+
postDigestElements.length = 0;
|
4923
|
+
}
|
4898
4924
|
|
4899
|
-
var classesAdded = updateData(add, true);
|
4900
|
-
var classesRemoved = updateData(remove, false);
|
4901
|
-
if ((!classesAdded && !classesRemoved) || postDigestElements.length > 1) return;
|
4902
|
-
|
4903
|
-
$rootScope.$$postDigest(function() {
|
4904
|
-
forEach(postDigestElements, function(element) {
|
4905
|
-
var data = postDigestQueue.get(element);
|
4906
|
-
if (data) {
|
4907
|
-
var existing = splitClasses(element.attr('class'));
|
4908
|
-
var toAdd = '';
|
4909
|
-
var toRemove = '';
|
4910
|
-
forEach(data, function(status, className) {
|
4911
|
-
var hasClass = !!existing[className];
|
4912
|
-
if (status !== hasClass) {
|
4913
|
-
if (status) {
|
4914
|
-
toAdd += (toAdd.length ? ' ' : '') + className;
|
4915
|
-
} else {
|
4916
|
-
toRemove += (toRemove.length ? ' ' : '') + className;
|
4917
|
-
}
|
4918
|
-
}
|
4919
|
-
});
|
4920
4925
|
|
4921
|
-
|
4922
|
-
|
4923
|
-
toRemove && jqLiteRemoveClass(elm, toRemove);
|
4924
|
-
});
|
4925
|
-
postDigestQueue.remove(element);
|
4926
|
-
}
|
4927
|
-
});
|
4926
|
+
function addRemoveClassesPostDigest(element, add, remove) {
|
4927
|
+
var data = postDigestQueue.get(element) || {};
|
4928
4928
|
|
4929
|
-
|
4930
|
-
|
4929
|
+
var classesAdded = updateData(data, add, true);
|
4930
|
+
var classesRemoved = updateData(data, remove, false);
|
4931
|
+
|
4932
|
+
if (classesAdded || classesRemoved) {
|
4933
|
+
|
4934
|
+
postDigestQueue.put(element, data);
|
4935
|
+
postDigestElements.push(element);
|
4936
|
+
|
4937
|
+
if (postDigestElements.length === 1) {
|
4938
|
+
$rootScope.$$postDigest(handleCSSClassChanges);
|
4939
|
+
}
|
4940
|
+
}
|
4931
4941
|
}
|
4932
4942
|
}];
|
4933
4943
|
};
|
@@ -5392,14 +5402,21 @@ var $CoreAnimateCssProvider = function() {
|
|
5392
5402
|
return this.getPromise().then(f1,f2);
|
5393
5403
|
},
|
5394
5404
|
'catch': function(f1) {
|
5395
|
-
return this.getPromise()
|
5405
|
+
return this.getPromise()['catch'](f1);
|
5396
5406
|
},
|
5397
5407
|
'finally': function(f1) {
|
5398
|
-
return this.getPromise()
|
5408
|
+
return this.getPromise()['finally'](f1);
|
5399
5409
|
}
|
5400
5410
|
};
|
5401
5411
|
|
5402
5412
|
return function(element, options) {
|
5413
|
+
// there is no point in applying the styles since
|
5414
|
+
// there is no animation that goes on at all in
|
5415
|
+
// this version of $animateCss.
|
5416
|
+
if (options.cleanupStyles) {
|
5417
|
+
options.from = options.to = null;
|
5418
|
+
}
|
5419
|
+
|
5403
5420
|
if (options.from) {
|
5404
5421
|
element.css(options.from);
|
5405
5422
|
options.from = null;
|
@@ -5528,7 +5545,7 @@ function Browser(window, document, $log, $sniffer) {
|
|
5528
5545
|
var cachedState, lastHistoryState,
|
5529
5546
|
lastBrowserUrl = location.href,
|
5530
5547
|
baseElement = document.find('base'),
|
5531
|
-
|
5548
|
+
pendingLocation = null;
|
5532
5549
|
|
5533
5550
|
cacheState();
|
5534
5551
|
lastHistoryState = cachedState;
|
@@ -5588,8 +5605,8 @@ function Browser(window, document, $log, $sniffer) {
|
|
5588
5605
|
// Do the assignment again so that those two variables are referentially identical.
|
5589
5606
|
lastHistoryState = cachedState;
|
5590
5607
|
} else {
|
5591
|
-
if (!sameBase ||
|
5592
|
-
|
5608
|
+
if (!sameBase || pendingLocation) {
|
5609
|
+
pendingLocation = url;
|
5593
5610
|
}
|
5594
5611
|
if (replace) {
|
5595
5612
|
location.replace(url);
|
@@ -5598,14 +5615,18 @@ function Browser(window, document, $log, $sniffer) {
|
|
5598
5615
|
} else {
|
5599
5616
|
location.hash = getHash(url);
|
5600
5617
|
}
|
5618
|
+
if (location.href !== url) {
|
5619
|
+
pendingLocation = url;
|
5620
|
+
}
|
5601
5621
|
}
|
5602
5622
|
return self;
|
5603
5623
|
// getter
|
5604
5624
|
} else {
|
5605
|
-
// -
|
5606
|
-
// the new location.href if a reload happened
|
5625
|
+
// - pendingLocation is needed as browsers don't allow to read out
|
5626
|
+
// the new location.href if a reload happened or if there is a bug like in iOS 9 (see
|
5627
|
+
// https://openradar.appspot.com/22186109).
|
5607
5628
|
// - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
|
5608
|
-
return
|
5629
|
+
return pendingLocation || location.href.replace(/%27/g,"'");
|
5609
5630
|
}
|
5610
5631
|
};
|
5611
5632
|
|
@@ -5627,6 +5648,7 @@ function Browser(window, document, $log, $sniffer) {
|
|
5627
5648
|
urlChangeInit = false;
|
5628
5649
|
|
5629
5650
|
function cacheStateAndFireUrlChange() {
|
5651
|
+
pendingLocation = null;
|
5630
5652
|
cacheState();
|
5631
5653
|
fireUrlChange();
|
5632
5654
|
}
|
@@ -5862,10 +5884,10 @@ function $BrowserProvider() {
|
|
5862
5884
|
$scope.keys = [];
|
5863
5885
|
$scope.cache = $cacheFactory('cacheId');
|
5864
5886
|
$scope.put = function(key, value) {
|
5865
|
-
if ($scope.cache.get(key)
|
5887
|
+
if (angular.isUndefined($scope.cache.get(key))) {
|
5866
5888
|
$scope.keys.push(key);
|
5867
5889
|
}
|
5868
|
-
$scope.cache.put(key, value
|
5890
|
+
$scope.cache.put(key, angular.isUndefined(value) ? null : value);
|
5869
5891
|
};
|
5870
5892
|
}]);
|
5871
5893
|
</file>
|
@@ -6341,18 +6363,24 @@ function $TemplateCacheProvider() {
|
|
6341
6363
|
* and other directives used in the directive's template will also be excluded from execution.
|
6342
6364
|
*
|
6343
6365
|
* #### `scope`
|
6344
|
-
*
|
6345
|
-
*
|
6346
|
-
*
|
6366
|
+
* The scope property can be `true`, an object or a falsy value:
|
6367
|
+
*
|
6368
|
+
* * **falsy:** No scope will be created for the directive. The directive will use its parent's scope.
|
6369
|
+
*
|
6370
|
+
* * **`true`:** A new child scope that prototypically inherits from its parent will be created for
|
6371
|
+
* the directive's element. If multiple directives on the same element request a new scope,
|
6372
|
+
* only one new scope is created. The new scope rule does not apply for the root of the template
|
6373
|
+
* since the root of the template always gets a new scope.
|
6347
6374
|
*
|
6348
|
-
*
|
6349
|
-
* normal scope in that it does not prototypically inherit from
|
6350
|
-
* when creating reusable components, which should not accidentally read or modify
|
6351
|
-
* parent scope.
|
6375
|
+
* * **`{...}` (an object hash):** A new "isolate" scope is created for the directive's element. The
|
6376
|
+
* 'isolate' scope differs from normal scope in that it does not prototypically inherit from its parent
|
6377
|
+
* scope. This is useful when creating reusable components, which should not accidentally read or modify
|
6378
|
+
* data in the parent scope.
|
6352
6379
|
*
|
6353
|
-
* The 'isolate' scope
|
6354
|
-
*
|
6355
|
-
*
|
6380
|
+
* The 'isolate' scope object hash defines a set of local scope properties derived from attributes on the
|
6381
|
+
* directive's element. These local properties are useful for aliasing values for templates. The keys in
|
6382
|
+
* the object hash map to the name of the property on the isolate scope; the values define how the property
|
6383
|
+
* is bound to the parent scope, via matching attributes on the directive's element:
|
6356
6384
|
*
|
6357
6385
|
* * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
|
6358
6386
|
* always a string since DOM attributes are strings. If no `attr` name is specified then the
|
@@ -6385,6 +6413,20 @@ function $TemplateCacheProvider() {
|
|
6385
6413
|
* For example, if the expression is `increment(amount)` then we can specify the amount value
|
6386
6414
|
* by calling the `localFn` as `localFn({amount: 22})`.
|
6387
6415
|
*
|
6416
|
+
* In general it's possible to apply more than one directive to one element, but there might be limitations
|
6417
|
+
* depending on the type of scope required by the directives. The following points will help explain these limitations.
|
6418
|
+
* For simplicity only two directives are taken into account, but it is also applicable for several directives:
|
6419
|
+
*
|
6420
|
+
* * **no scope** + **no scope** => Two directives which don't require their own scope will use their parent's scope
|
6421
|
+
* * **child scope** + **no scope** => Both directives will share one single child scope
|
6422
|
+
* * **child scope** + **child scope** => Both directives will share one single child scope
|
6423
|
+
* * **isolated scope** + **no scope** => The isolated directive will use it's own created isolated scope. The other directive will use
|
6424
|
+
* its parent's scope
|
6425
|
+
* * **isolated scope** + **child scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives cannot
|
6426
|
+
* be applied to the same element.
|
6427
|
+
* * **isolated scope** + **isolated scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives
|
6428
|
+
* cannot be applied to the same element.
|
6429
|
+
*
|
6388
6430
|
*
|
6389
6431
|
* #### `bindToController`
|
6390
6432
|
* When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will
|
@@ -6393,7 +6435,7 @@ function $TemplateCacheProvider() {
|
|
6393
6435
|
*
|
6394
6436
|
* #### `controller`
|
6395
6437
|
* Controller constructor function. The controller is instantiated before the
|
6396
|
-
* pre-linking phase and
|
6438
|
+
* pre-linking phase and can be accessed by other directives (see
|
6397
6439
|
* `require` attribute). This allows the directives to communicate with each other and augment
|
6398
6440
|
* each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:
|
6399
6441
|
*
|
@@ -6433,9 +6475,10 @@ function $TemplateCacheProvider() {
|
|
6433
6475
|
*
|
6434
6476
|
* #### `controllerAs`
|
6435
6477
|
* Identifier name for a reference to the controller in the directive's scope.
|
6436
|
-
* This allows the controller to be referenced from the directive template.
|
6437
|
-
*
|
6438
|
-
* directive
|
6478
|
+
* This allows the controller to be referenced from the directive template. This is especially
|
6479
|
+
* useful when a directive is used as component, i.e. with an `isolate` scope. It's also possible
|
6480
|
+
* to use it in a directive without an `isolate` / `new` scope, but you need to be aware that the
|
6481
|
+
* `controllerAs` reference might overwrite a property that already exists on the parent scope.
|
6439
6482
|
*
|
6440
6483
|
*
|
6441
6484
|
* #### `restrict`
|
@@ -7272,7 +7315,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
7272
7315
|
|
7273
7316
|
var node = this.$$element[0],
|
7274
7317
|
booleanKey = getBooleanAttrName(node, key),
|
7275
|
-
aliasedKey = getAliasedAttrName(
|
7318
|
+
aliasedKey = getAliasedAttrName(key),
|
7276
7319
|
observer = key,
|
7277
7320
|
nodeName;
|
7278
7321
|
|
@@ -7339,7 +7382,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
7339
7382
|
}
|
7340
7383
|
|
7341
7384
|
if (writeAttr !== false) {
|
7342
|
-
if (value === null || value
|
7385
|
+
if (value === null || isUndefined(value)) {
|
7343
7386
|
this.$$element.removeAttr(attrName);
|
7344
7387
|
} else {
|
7345
7388
|
this.$$element.attr(attrName, value);
|
@@ -8305,7 +8348,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
8305
8348
|
i = 0, ii = directives.length; i < ii; i++) {
|
8306
8349
|
try {
|
8307
8350
|
directive = directives[i];
|
8308
|
-
if ((maxPriority
|
8351
|
+
if ((isUndefined(maxPriority) || maxPriority > directive.priority) &&
|
8309
8352
|
directive.restrict.indexOf(location) != -1) {
|
8310
8353
|
if (startAttrName) {
|
8311
8354
|
directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
|
@@ -8601,7 +8644,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
8601
8644
|
compile: function() {
|
8602
8645
|
return {
|
8603
8646
|
pre: function attrInterpolatePreLinkFn(scope, element, attr) {
|
8604
|
-
var $$observers = (attr.$$observers || (attr.$$observers =
|
8647
|
+
var $$observers = (attr.$$observers || (attr.$$observers = createMap()));
|
8605
8648
|
|
8606
8649
|
if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
|
8607
8650
|
throw $compileMinErr('nodomevents',
|
@@ -9653,28 +9696,18 @@ function $HttpProvider() {
|
|
9653
9696
|
*
|
9654
9697
|
*
|
9655
9698
|
* ## General usage
|
9656
|
-
* The `$http` service is a function which takes a single argument — a configuration object —
|
9699
|
+
* The `$http` service is a function which takes a single argument — a {@link $http#usage configuration object} —
|
9657
9700
|
* that is used to generate an HTTP request and returns a {@link ng.$q promise}.
|
9658
9701
|
*
|
9659
9702
|
* ```js
|
9660
|
-
* // Simple GET request example
|
9661
|
-
* $http
|
9662
|
-
*
|
9663
|
-
*
|
9664
|
-
*
|
9665
|
-
* }, function(response) {
|
9666
|
-
* // called asynchronously if an error occurs
|
9667
|
-
* // or server returns response with an error status.
|
9668
|
-
* });
|
9669
|
-
* ```
|
9670
|
-
*
|
9671
|
-
* ```js
|
9672
|
-
* // Simple POST request example (passing data) :
|
9673
|
-
* $http.post('/someUrl', {msg:'hello word!'}).
|
9674
|
-
* then(function(response) {
|
9703
|
+
* // Simple GET request example:
|
9704
|
+
* $http({
|
9705
|
+
* method: 'GET',
|
9706
|
+
* url: '/someUrl'
|
9707
|
+
* }).then(function successCallback(response) {
|
9675
9708
|
* // this callback will be called asynchronously
|
9676
9709
|
* // when the response is available
|
9677
|
-
* }, function(response) {
|
9710
|
+
* }, function errorCallback(response) {
|
9678
9711
|
* // called asynchronously if an error occurs
|
9679
9712
|
* // or server returns response with an error status.
|
9680
9713
|
* });
|
@@ -9694,25 +9727,16 @@ function $HttpProvider() {
|
|
9694
9727
|
* XMLHttpRequest will transparently follow it, meaning that the error callback will not be
|
9695
9728
|
* called for such responses.
|
9696
9729
|
*
|
9697
|
-
* ## Writing Unit Tests that use $http
|
9698
|
-
* When unit testing (using {@link ngMock ngMock}), it is necessary to call
|
9699
|
-
* {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending
|
9700
|
-
* request using trained responses.
|
9701
|
-
*
|
9702
|
-
* ```
|
9703
|
-
* $httpBackend.expectGET(...);
|
9704
|
-
* $http.get(...);
|
9705
|
-
* $httpBackend.flush();
|
9706
|
-
* ```
|
9707
9730
|
*
|
9708
9731
|
* ## Shortcut methods
|
9709
9732
|
*
|
9710
9733
|
* Shortcut methods are also available. All shortcut methods require passing in the URL, and
|
9711
|
-
* request data must be passed in for POST/PUT requests.
|
9734
|
+
* request data must be passed in for POST/PUT requests. An optional config can be passed as the
|
9735
|
+
* last argument.
|
9712
9736
|
*
|
9713
9737
|
* ```js
|
9714
|
-
* $http.get('/someUrl').then(successCallback);
|
9715
|
-
* $http.post('/someUrl', data).then(successCallback);
|
9738
|
+
* $http.get('/someUrl', config).then(successCallback, errorCallback);
|
9739
|
+
* $http.post('/someUrl', data, config).then(successCallback, errorCallback);
|
9716
9740
|
* ```
|
9717
9741
|
*
|
9718
9742
|
* Complete list of shortcut methods:
|
@@ -9726,6 +9750,17 @@ function $HttpProvider() {
|
|
9726
9750
|
* - {@link ng.$http#patch $http.patch}
|
9727
9751
|
*
|
9728
9752
|
*
|
9753
|
+
* ## Writing Unit Tests that use $http
|
9754
|
+
* When unit testing (using {@link ngMock ngMock}), it is necessary to call
|
9755
|
+
* {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending
|
9756
|
+
* request using trained responses.
|
9757
|
+
*
|
9758
|
+
* ```
|
9759
|
+
* $httpBackend.expectGET(...);
|
9760
|
+
* $http.get(...);
|
9761
|
+
* $httpBackend.flush();
|
9762
|
+
* ```
|
9763
|
+
*
|
9729
9764
|
* ## Deprecation Notice
|
9730
9765
|
* <div class="alert alert-danger">
|
9731
9766
|
* The `$http` legacy promise methods `success` and `error` have been deprecated.
|
@@ -9883,7 +9918,7 @@ function $HttpProvider() {
|
|
9883
9918
|
*
|
9884
9919
|
* There are two kinds of interceptors (and two kinds of rejection interceptors):
|
9885
9920
|
*
|
9886
|
-
* * `request`: interceptors get called with a http
|
9921
|
+
* * `request`: interceptors get called with a http {@link $http#usage config} object. The function is free to
|
9887
9922
|
* modify the `config` object or create a new one. The function needs to return the `config`
|
9888
9923
|
* object directly, or a promise containing the `config` or a new `config` object.
|
9889
9924
|
* * `requestError`: interceptor gets called when a previous interceptor threw an error or
|
@@ -10517,8 +10552,8 @@ function $HttpProvider() {
|
|
10517
10552
|
* Resolves the raw $http promise.
|
10518
10553
|
*/
|
10519
10554
|
function resolvePromise(response, status, headers, statusText) {
|
10520
|
-
//
|
10521
|
-
status =
|
10555
|
+
//status: HTTP response status code, 0, -1 (aborted by timeout / promise)
|
10556
|
+
status = status >= -1 ? status : 0;
|
10522
10557
|
|
10523
10558
|
(isSuccess(status) ? deferred.resolve : deferred.reject)({
|
10524
10559
|
data: response,
|
@@ -10549,8 +10584,33 @@ function $HttpProvider() {
|
|
10549
10584
|
}];
|
10550
10585
|
}
|
10551
10586
|
|
10552
|
-
|
10553
|
-
|
10587
|
+
/**
|
10588
|
+
* @ngdoc service
|
10589
|
+
* @name $xhrFactory
|
10590
|
+
*
|
10591
|
+
* @description
|
10592
|
+
* Factory function used to create XMLHttpRequest objects.
|
10593
|
+
*
|
10594
|
+
* Replace or decorate this service to create your own custom XMLHttpRequest objects.
|
10595
|
+
*
|
10596
|
+
* ```
|
10597
|
+
* angular.module('myApp', [])
|
10598
|
+
* .factory('$xhrFactory', function() {
|
10599
|
+
* return function createXhr(method, url) {
|
10600
|
+
* return new window.XMLHttpRequest({mozSystem: true});
|
10601
|
+
* };
|
10602
|
+
* });
|
10603
|
+
* ```
|
10604
|
+
*
|
10605
|
+
* @param {string} method HTTP method of the request (GET, POST, PUT, ..)
|
10606
|
+
* @param {string} url URL of the request.
|
10607
|
+
*/
|
10608
|
+
function $xhrFactoryProvider() {
|
10609
|
+
this.$get = function() {
|
10610
|
+
return function createXhr() {
|
10611
|
+
return new window.XMLHttpRequest();
|
10612
|
+
};
|
10613
|
+
};
|
10554
10614
|
}
|
10555
10615
|
|
10556
10616
|
/**
|
@@ -10558,6 +10618,7 @@ function createXhr() {
|
|
10558
10618
|
* @name $httpBackend
|
10559
10619
|
* @requires $window
|
10560
10620
|
* @requires $document
|
10621
|
+
* @requires $xhrFactory
|
10561
10622
|
*
|
10562
10623
|
* @description
|
10563
10624
|
* HTTP backend used by the {@link ng.$http service} that delegates to
|
@@ -10570,8 +10631,8 @@ function createXhr() {
|
|
10570
10631
|
* $httpBackend} which can be trained with responses.
|
10571
10632
|
*/
|
10572
10633
|
function $HttpBackendProvider() {
|
10573
|
-
this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {
|
10574
|
-
return createHttpBackend($browser,
|
10634
|
+
this.$get = ['$browser', '$window', '$document', '$xhrFactory', function($browser, $window, $document, $xhrFactory) {
|
10635
|
+
return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]);
|
10575
10636
|
}];
|
10576
10637
|
}
|
10577
10638
|
|
@@ -10595,7 +10656,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
|
|
10595
10656
|
});
|
10596
10657
|
} else {
|
10597
10658
|
|
10598
|
-
var xhr = createXhr();
|
10659
|
+
var xhr = createXhr(method, url);
|
10599
10660
|
|
10600
10661
|
xhr.open(method, url, true);
|
10601
10662
|
forEach(headers, function(value, key) {
|
@@ -10658,7 +10719,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
|
|
10658
10719
|
}
|
10659
10720
|
}
|
10660
10721
|
|
10661
|
-
xhr.send(post);
|
10722
|
+
xhr.send(isUndefined(post) ? null : post);
|
10662
10723
|
}
|
10663
10724
|
|
10664
10725
|
if (timeout > 0) {
|
@@ -10675,7 +10736,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
|
|
10675
10736
|
|
10676
10737
|
function completeRequest(callback, status, response, headersString, statusText) {
|
10677
10738
|
// cancel timeout and subsequent timeout promise resolution
|
10678
|
-
if (timeoutId
|
10739
|
+
if (isDefined(timeoutId)) {
|
10679
10740
|
$browserDefer.cancel(timeoutId);
|
10680
10741
|
}
|
10681
10742
|
jsonpDone = xhr = null;
|
@@ -10861,7 +10922,7 @@ function $InterpolateProvider() {
|
|
10861
10922
|
* ```js
|
10862
10923
|
* var $interpolate = ...; // injected
|
10863
10924
|
* var exp = $interpolate('Hello {{name | uppercase}}!');
|
10864
|
-
* expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');
|
10925
|
+
* expect(exp({name:'Angular'})).toEqual('Hello ANGULAR!');
|
10865
10926
|
* ```
|
10866
10927
|
*
|
10867
10928
|
* `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is
|
@@ -11414,14 +11475,14 @@ function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {
|
|
11414
11475
|
var appUrl, prevAppUrl;
|
11415
11476
|
var rewrittenUrl;
|
11416
11477
|
|
11417
|
-
if ((appUrl = beginsWith(appBase, url))
|
11478
|
+
if (isDefined(appUrl = beginsWith(appBase, url))) {
|
11418
11479
|
prevAppUrl = appUrl;
|
11419
|
-
if ((appUrl = beginsWith(basePrefix, appUrl))
|
11480
|
+
if (isDefined(appUrl = beginsWith(basePrefix, appUrl))) {
|
11420
11481
|
rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
|
11421
11482
|
} else {
|
11422
11483
|
rewrittenUrl = appBase + prevAppUrl;
|
11423
11484
|
}
|
11424
|
-
} else if ((appUrl = beginsWith(appBaseNoFile, url))
|
11485
|
+
} else if (isDefined(appUrl = beginsWith(appBaseNoFile, url))) {
|
11425
11486
|
rewrittenUrl = appBaseNoFile + appUrl;
|
11426
11487
|
} else if (appBaseNoFile == url + '/') {
|
11427
11488
|
rewrittenUrl = appBaseNoFile;
|
@@ -12474,6 +12535,25 @@ function ensureSafeMemberName(name, fullExpression) {
|
|
12474
12535
|
return name;
|
12475
12536
|
}
|
12476
12537
|
|
12538
|
+
function getStringValue(name, fullExpression) {
|
12539
|
+
// From the JavaScript docs:
|
12540
|
+
// Property names must be strings. This means that non-string objects cannot be used
|
12541
|
+
// as keys in an object. Any non-string object, including a number, is typecasted
|
12542
|
+
// into a string via the toString method.
|
12543
|
+
//
|
12544
|
+
// So, to ensure that we are checking the same `name` that JavaScript would use,
|
12545
|
+
// we cast it to a string, if possible.
|
12546
|
+
// Doing `name + ''` can cause a repl error if the result to `toString` is not a string,
|
12547
|
+
// this is, this will handle objects that misbehave.
|
12548
|
+
name = name + '';
|
12549
|
+
if (!isString(name)) {
|
12550
|
+
throw $parseMinErr('iseccst',
|
12551
|
+
'Cannot convert object to primitive value! '
|
12552
|
+
+ 'Expression: {0}', fullExpression);
|
12553
|
+
}
|
12554
|
+
return name;
|
12555
|
+
}
|
12556
|
+
|
12477
12557
|
function ensureSafeObject(obj, fullExpression) {
|
12478
12558
|
// nifty check if obj is Function that is fast and works across iframes and other contexts
|
12479
12559
|
if (obj) {
|
@@ -12519,6 +12599,16 @@ function ensureSafeFunction(obj, fullExpression) {
|
|
12519
12599
|
}
|
12520
12600
|
}
|
12521
12601
|
|
12602
|
+
function ensureSafeAssignContext(obj, fullExpression) {
|
12603
|
+
if (obj) {
|
12604
|
+
if (obj === (0).constructor || obj === (false).constructor || obj === ''.constructor ||
|
12605
|
+
obj === {}.constructor || obj === [].constructor || obj === Function.constructor) {
|
12606
|
+
throw $parseMinErr('isecaf',
|
12607
|
+
'Assigning to a constructor is disallowed! Expression: {0}', fullExpression);
|
12608
|
+
}
|
12609
|
+
}
|
12610
|
+
}
|
12611
|
+
|
12522
12612
|
var OPERATORS = createMap();
|
12523
12613
|
forEach('+ - * / % === !== == != < > <= >= && || ! = |'.split(' '), function(operator) { OPERATORS[operator] = true; });
|
12524
12614
|
var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
|
@@ -13200,6 +13290,7 @@ ASTCompiler.prototype = {
|
|
13200
13290
|
this.state.computing = 'assign';
|
13201
13291
|
var result = this.nextId();
|
13202
13292
|
this.recurse(assignable, result);
|
13293
|
+
this.return_(result);
|
13203
13294
|
extra = 'fn.assign=' + this.generateFunction('assign', 's,v,l');
|
13204
13295
|
}
|
13205
13296
|
var toWatch = getInputs(ast.body);
|
@@ -13232,6 +13323,8 @@ ASTCompiler.prototype = {
|
|
13232
13323
|
'ensureSafeMemberName',
|
13233
13324
|
'ensureSafeObject',
|
13234
13325
|
'ensureSafeFunction',
|
13326
|
+
'getStringValue',
|
13327
|
+
'ensureSafeAssignContext',
|
13235
13328
|
'ifDefined',
|
13236
13329
|
'plus',
|
13237
13330
|
'text',
|
@@ -13240,6 +13333,8 @@ ASTCompiler.prototype = {
|
|
13240
13333
|
ensureSafeMemberName,
|
13241
13334
|
ensureSafeObject,
|
13242
13335
|
ensureSafeFunction,
|
13336
|
+
getStringValue,
|
13337
|
+
ensureSafeAssignContext,
|
13243
13338
|
ifDefined,
|
13244
13339
|
plusFn,
|
13245
13340
|
expression);
|
@@ -13383,6 +13478,7 @@ ASTCompiler.prototype = {
|
|
13383
13478
|
if (ast.computed) {
|
13384
13479
|
right = self.nextId();
|
13385
13480
|
self.recurse(ast.property, right);
|
13481
|
+
self.getStringValue(right);
|
13386
13482
|
self.addEnsureSafeMemberName(right);
|
13387
13483
|
if (create && create !== 1) {
|
13388
13484
|
self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}'));
|
@@ -13466,6 +13562,7 @@ ASTCompiler.prototype = {
|
|
13466
13562
|
self.if_(self.notNull(left.context), function() {
|
13467
13563
|
self.recurse(ast.right, right);
|
13468
13564
|
self.addEnsureSafeObject(self.member(left.context, left.name, left.computed));
|
13565
|
+
self.addEnsureSafeAssignContext(left.context);
|
13469
13566
|
expression = self.member(left.context, left.name, left.computed) + ast.operator + right;
|
13470
13567
|
self.assign(intoId, expression);
|
13471
13568
|
recursionFn(intoId || expression);
|
@@ -13591,6 +13688,10 @@ ASTCompiler.prototype = {
|
|
13591
13688
|
this.current().body.push(this.ensureSafeFunction(item), ';');
|
13592
13689
|
},
|
13593
13690
|
|
13691
|
+
addEnsureSafeAssignContext: function(item) {
|
13692
|
+
this.current().body.push(this.ensureSafeAssignContext(item), ';');
|
13693
|
+
},
|
13694
|
+
|
13594
13695
|
ensureSafeObject: function(item) {
|
13595
13696
|
return 'ensureSafeObject(' + item + ',text)';
|
13596
13697
|
},
|
@@ -13603,6 +13704,14 @@ ASTCompiler.prototype = {
|
|
13603
13704
|
return 'ensureSafeFunction(' + item + ',text)';
|
13604
13705
|
},
|
13605
13706
|
|
13707
|
+
getStringValue: function(item) {
|
13708
|
+
this.assign(item, 'getStringValue(' + item + ',text)');
|
13709
|
+
},
|
13710
|
+
|
13711
|
+
ensureSafeAssignContext: function(item) {
|
13712
|
+
return 'ensureSafeAssignContext(' + item + ',text)';
|
13713
|
+
},
|
13714
|
+
|
13606
13715
|
lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) {
|
13607
13716
|
var self = this;
|
13608
13717
|
return function() {
|
@@ -13780,6 +13889,7 @@ ASTInterpreter.prototype = {
|
|
13780
13889
|
var lhs = left(scope, locals, assign, inputs);
|
13781
13890
|
var rhs = right(scope, locals, assign, inputs);
|
13782
13891
|
ensureSafeObject(lhs.value, self.expression);
|
13892
|
+
ensureSafeAssignContext(lhs.context);
|
13783
13893
|
lhs.context[lhs.name] = rhs;
|
13784
13894
|
return context ? {value: rhs} : rhs;
|
13785
13895
|
};
|
@@ -13977,6 +14087,7 @@ ASTInterpreter.prototype = {
|
|
13977
14087
|
var value;
|
13978
14088
|
if (lhs != null) {
|
13979
14089
|
rhs = right(scope, locals, assign, inputs);
|
14090
|
+
rhs = getStringValue(rhs);
|
13980
14091
|
ensureSafeMemberName(rhs, expression);
|
13981
14092
|
if (create && create !== 1 && lhs && !(lhs[rhs])) {
|
13982
14093
|
lhs[rhs] = {};
|
@@ -14917,7 +15028,7 @@ function $$RAFProvider() { //rAF
|
|
14917
15028
|
$window.webkitCancelRequestAnimationFrame;
|
14918
15029
|
|
14919
15030
|
var rafSupported = !!requestAnimationFrame;
|
14920
|
-
var
|
15031
|
+
var raf = rafSupported
|
14921
15032
|
? function(fn) {
|
14922
15033
|
var id = requestAnimationFrame(fn);
|
14923
15034
|
return function() {
|
@@ -14931,47 +15042,9 @@ function $$RAFProvider() { //rAF
|
|
14931
15042
|
};
|
14932
15043
|
};
|
14933
15044
|
|
14934
|
-
|
14935
|
-
|
14936
|
-
var cancelLastRAF;
|
14937
|
-
var taskCount = 0;
|
14938
|
-
var taskQueue = [];
|
14939
|
-
return queueFn;
|
14940
|
-
|
14941
|
-
function flush() {
|
14942
|
-
for (var i = 0; i < taskQueue.length; i++) {
|
14943
|
-
var task = taskQueue[i];
|
14944
|
-
if (task) {
|
14945
|
-
taskQueue[i] = null;
|
14946
|
-
task();
|
14947
|
-
}
|
14948
|
-
}
|
14949
|
-
taskCount = taskQueue.length = 0;
|
14950
|
-
}
|
14951
|
-
|
14952
|
-
function queueFn(asyncFn) {
|
14953
|
-
var index = taskQueue.length;
|
15045
|
+
raf.supported = rafSupported;
|
14954
15046
|
|
14955
|
-
|
14956
|
-
taskQueue.push(asyncFn);
|
14957
|
-
|
14958
|
-
if (index === 0) {
|
14959
|
-
cancelLastRAF = rafFn(flush);
|
14960
|
-
}
|
14961
|
-
|
14962
|
-
return function cancelQueueFn() {
|
14963
|
-
if (index >= 0) {
|
14964
|
-
taskQueue[index] = null;
|
14965
|
-
index = null;
|
14966
|
-
|
14967
|
-
if (--taskCount === 0 && cancelLastRAF) {
|
14968
|
-
cancelLastRAF();
|
14969
|
-
cancelLastRAF = null;
|
14970
|
-
taskQueue.length = 0;
|
14971
|
-
}
|
14972
|
-
}
|
14973
|
-
};
|
14974
|
-
}
|
15047
|
+
return raf;
|
14975
15048
|
}];
|
14976
15049
|
}
|
14977
15050
|
|
@@ -15228,10 +15301,10 @@ function $RootScopeProvider() {
|
|
15228
15301
|
* Registers a `listener` callback to be executed whenever the `watchExpression` changes.
|
15229
15302
|
*
|
15230
15303
|
* - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest
|
15231
|
-
* $digest()} and should return the value that will be watched. (
|
15232
|
-
*
|
15233
|
-
* `watchExpression`
|
15234
|
-
*
|
15304
|
+
* $digest()} and should return the value that will be watched. (`watchExpression` should not change
|
15305
|
+
* its value when executed multiple times with the same input because it may be executed multiple
|
15306
|
+
* times by {@link ng.$rootScope.Scope#$digest $digest()}. That is, `watchExpression` should be
|
15307
|
+
* [idempotent](http://en.wikipedia.org/wiki/Idempotence).
|
15235
15308
|
* - The `listener` is called only when the value from the current `watchExpression` and the
|
15236
15309
|
* previous call to `watchExpression` are not equal (with the exception of the initial run,
|
15237
15310
|
* see below). Inequality is determined according to reference inequality,
|
@@ -15580,7 +15653,7 @@ function $RootScopeProvider() {
|
|
15580
15653
|
// copy the items to oldValue and look for changes.
|
15581
15654
|
newLength = 0;
|
15582
15655
|
for (key in newValue) {
|
15583
|
-
if (
|
15656
|
+
if (hasOwnProperty.call(newValue, key)) {
|
15584
15657
|
newLength++;
|
15585
15658
|
newItem = newValue[key];
|
15586
15659
|
oldItem = oldValue[key];
|
@@ -15602,7 +15675,7 @@ function $RootScopeProvider() {
|
|
15602
15675
|
// we used to have more keys, need to find them and destroy them.
|
15603
15676
|
changeDetected++;
|
15604
15677
|
for (key in oldValue) {
|
15605
|
-
if (!
|
15678
|
+
if (!hasOwnProperty.call(newValue, key)) {
|
15606
15679
|
oldLength--;
|
15607
15680
|
delete oldValue[key];
|
15608
15681
|
}
|
@@ -16687,7 +16760,7 @@ function $SceDelegateProvider() {
|
|
16687
16760
|
'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',
|
16688
16761
|
type, trustedValue);
|
16689
16762
|
}
|
16690
|
-
if (trustedValue === null || trustedValue
|
16763
|
+
if (trustedValue === null || isUndefined(trustedValue) || trustedValue === '') {
|
16691
16764
|
return trustedValue;
|
16692
16765
|
}
|
16693
16766
|
// All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting
|
@@ -16742,7 +16815,7 @@ function $SceDelegateProvider() {
|
|
16742
16815
|
* `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception.
|
16743
16816
|
*/
|
16744
16817
|
function getTrusted(type, maybeTrusted) {
|
16745
|
-
if (maybeTrusted === null || maybeTrusted
|
16818
|
+
if (maybeTrusted === null || isUndefined(maybeTrusted) || maybeTrusted === '') {
|
16746
16819
|
return maybeTrusted;
|
16747
16820
|
}
|
16748
16821
|
var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
|
@@ -18003,7 +18076,7 @@ function $$CookieReader($document) {
|
|
18003
18076
|
// the first value that is seen for a cookie is the most
|
18004
18077
|
// specific one. values for the same cookie name that
|
18005
18078
|
// follow are for less specific paths.
|
18006
|
-
if (lastCookies[name]
|
18079
|
+
if (isUndefined(lastCookies[name])) {
|
18007
18080
|
lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));
|
18008
18081
|
}
|
18009
18082
|
}
|
@@ -18651,6 +18724,7 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
|
|
18651
18724
|
if (fractionSize > 0 && number < 1) {
|
18652
18725
|
formatedText = number.toFixed(fractionSize);
|
18653
18726
|
number = parseFloat(formatedText);
|
18727
|
+
formatedText = formatedText.replace(DECIMAL_SEP, decimalSep);
|
18654
18728
|
}
|
18655
18729
|
}
|
18656
18730
|
|
@@ -19949,6 +20023,7 @@ function nullFormRenameControl(control, name) {
|
|
19949
20023
|
* @property {boolean} $dirty True if user has already interacted with the form.
|
19950
20024
|
* @property {boolean} $valid True if all of the containing forms and controls are valid.
|
19951
20025
|
* @property {boolean} $invalid True if at least one containing control or form is invalid.
|
20026
|
+
* @property {boolean} $pending True if at least one containing control or form is pending.
|
19952
20027
|
* @property {boolean} $submitted True if user has submitted the form even if its invalid.
|
19953
20028
|
*
|
19954
20029
|
* @property {Object} $error Is an object hash, containing references to controls or
|
@@ -19988,8 +20063,6 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
|
19988
20063
|
var form = this,
|
19989
20064
|
controls = [];
|
19990
20065
|
|
19991
|
-
var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl;
|
19992
|
-
|
19993
20066
|
// init state
|
19994
20067
|
form.$error = {};
|
19995
20068
|
form.$$success = {};
|
@@ -20000,8 +20073,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
|
20000
20073
|
form.$valid = true;
|
20001
20074
|
form.$invalid = false;
|
20002
20075
|
form.$submitted = false;
|
20003
|
-
|
20004
|
-
parentForm.$addControl(form);
|
20076
|
+
form.$$parentForm = nullFormCtrl;
|
20005
20077
|
|
20006
20078
|
/**
|
20007
20079
|
* @ngdoc method
|
@@ -20040,11 +20112,23 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
|
20040
20112
|
/**
|
20041
20113
|
* @ngdoc method
|
20042
20114
|
* @name form.FormController#$addControl
|
20115
|
+
* @param {object} control control object, either a {@link form.FormController} or an
|
20116
|
+
* {@link ngModel.NgModelController}
|
20043
20117
|
*
|
20044
20118
|
* @description
|
20045
|
-
* Register a control with the form.
|
20119
|
+
* Register a control with the form. Input elements using ngModelController do this automatically
|
20120
|
+
* when they are linked.
|
20046
20121
|
*
|
20047
|
-
*
|
20122
|
+
* Note that the current state of the control will not be reflected on the new parent form. This
|
20123
|
+
* is not an issue with normal use, as freshly compiled and linked controls are in a `$pristine`
|
20124
|
+
* state.
|
20125
|
+
*
|
20126
|
+
* However, if the method is used programmatically, for example by adding dynamically created controls,
|
20127
|
+
* or controls that have been previously removed without destroying their corresponding DOM element,
|
20128
|
+
* it's the developers responsiblity to make sure the current state propagates to the parent form.
|
20129
|
+
*
|
20130
|
+
* For example, if an input control is added that is already `$dirty` and has `$error` properties,
|
20131
|
+
* calling `$setDirty()` and `$validate()` afterwards will propagate the state to the parent form.
|
20048
20132
|
*/
|
20049
20133
|
form.$addControl = function(control) {
|
20050
20134
|
// Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
|
@@ -20055,6 +20139,8 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
|
20055
20139
|
if (control.$name) {
|
20056
20140
|
form[control.$name] = control;
|
20057
20141
|
}
|
20142
|
+
|
20143
|
+
control.$$parentForm = form;
|
20058
20144
|
};
|
20059
20145
|
|
20060
20146
|
// Private API: rename a form control
|
@@ -20071,11 +20157,18 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
|
20071
20157
|
/**
|
20072
20158
|
* @ngdoc method
|
20073
20159
|
* @name form.FormController#$removeControl
|
20160
|
+
* @param {object} control control object, either a {@link form.FormController} or an
|
20161
|
+
* {@link ngModel.NgModelController}
|
20074
20162
|
*
|
20075
20163
|
* @description
|
20076
20164
|
* Deregister a control from the form.
|
20077
20165
|
*
|
20078
20166
|
* Input elements using ngModelController do this automatically when they are destroyed.
|
20167
|
+
*
|
20168
|
+
* Note that only the removed control's validation state (`$errors`etc.) will be removed from the
|
20169
|
+
* form. `$dirty`, `$submitted` states will not be changed, because the expected behavior can be
|
20170
|
+
* different from case to case. For example, removing the only `$dirty` control from a form may or
|
20171
|
+
* may not mean that the form is still `$dirty`.
|
20079
20172
|
*/
|
20080
20173
|
form.$removeControl = function(control) {
|
20081
20174
|
if (control.$name && form[control.$name] === control) {
|
@@ -20092,6 +20185,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
|
20092
20185
|
});
|
20093
20186
|
|
20094
20187
|
arrayRemove(controls, control);
|
20188
|
+
control.$$parentForm = nullFormCtrl;
|
20095
20189
|
};
|
20096
20190
|
|
20097
20191
|
|
@@ -20128,7 +20222,6 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
|
20128
20222
|
delete object[property];
|
20129
20223
|
}
|
20130
20224
|
},
|
20131
|
-
parentForm: parentForm,
|
20132
20225
|
$animate: $animate
|
20133
20226
|
});
|
20134
20227
|
|
@@ -20147,7 +20240,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
|
20147
20240
|
$animate.addClass(element, DIRTY_CLASS);
|
20148
20241
|
form.$dirty = true;
|
20149
20242
|
form.$pristine = false;
|
20150
|
-
parentForm.$setDirty();
|
20243
|
+
form.$$parentForm.$setDirty();
|
20151
20244
|
};
|
20152
20245
|
|
20153
20246
|
/**
|
@@ -20203,7 +20296,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
|
20203
20296
|
form.$setSubmitted = function() {
|
20204
20297
|
$animate.addClass(element, SUBMITTED_CLASS);
|
20205
20298
|
form.$submitted = true;
|
20206
|
-
parentForm.$setSubmitted();
|
20299
|
+
form.$$parentForm.$setSubmitted();
|
20207
20300
|
};
|
20208
20301
|
}
|
20209
20302
|
|
@@ -20253,6 +20346,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
|
20253
20346
|
* # CSS classes
|
20254
20347
|
* - `ng-valid` is set if the form is valid.
|
20255
20348
|
* - `ng-invalid` is set if the form is invalid.
|
20349
|
+
* - `ng-pending` is set if the form is pending.
|
20256
20350
|
* - `ng-pristine` is set if the form is pristine.
|
20257
20351
|
* - `ng-dirty` is set if the form is dirty.
|
20258
20352
|
* - `ng-submitted` is set if the form was submitted.
|
@@ -20328,7 +20422,6 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
|
20328
20422
|
</script>
|
20329
20423
|
<style>
|
20330
20424
|
.my-form {
|
20331
|
-
-webkit-transition:all linear 0.5s;
|
20332
20425
|
transition:all linear 0.5s;
|
20333
20426
|
background: transparent;
|
20334
20427
|
}
|
@@ -20377,6 +20470,7 @@ var formDirectiveFactory = function(isNgForm) {
|
|
20377
20470
|
var formDirective = {
|
20378
20471
|
name: 'form',
|
20379
20472
|
restrict: isNgForm ? 'EAC' : 'E',
|
20473
|
+
require: ['form', '^^?form'], //first is the form's own ctrl, second is an optional parent form
|
20380
20474
|
controller: FormController,
|
20381
20475
|
compile: function ngFormCompile(formElement, attr) {
|
20382
20476
|
// Setup initial state of the control
|
@@ -20385,7 +20479,9 @@ var formDirectiveFactory = function(isNgForm) {
|
|
20385
20479
|
var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false);
|
20386
20480
|
|
20387
20481
|
return {
|
20388
|
-
pre: function ngFormPreLink(scope, formElement, attr,
|
20482
|
+
pre: function ngFormPreLink(scope, formElement, attr, ctrls) {
|
20483
|
+
var controller = ctrls[0];
|
20484
|
+
|
20389
20485
|
// if `action` attr is not present on the form, prevent the default action (submission)
|
20390
20486
|
if (!('action' in attr)) {
|
20391
20487
|
// we can't use jq events because if a form is destroyed during submission the default
|
@@ -20414,7 +20510,9 @@ var formDirectiveFactory = function(isNgForm) {
|
|
20414
20510
|
});
|
20415
20511
|
}
|
20416
20512
|
|
20417
|
-
var parentFormCtrl = controller.$$parentForm;
|
20513
|
+
var parentFormCtrl = ctrls[1] || controller.$$parentForm;
|
20514
|
+
parentFormCtrl.$addControl(controller);
|
20515
|
+
|
20418
20516
|
var setter = nameAttr ? getSetter(controller.$name) : noop;
|
20419
20517
|
|
20420
20518
|
if (nameAttr) {
|
@@ -20422,13 +20520,13 @@ var formDirectiveFactory = function(isNgForm) {
|
|
20422
20520
|
attr.$observe(nameAttr, function(newValue) {
|
20423
20521
|
if (controller.$name === newValue) return;
|
20424
20522
|
setter(scope, undefined);
|
20425
|
-
|
20523
|
+
controller.$$parentForm.$$renameControl(controller, newValue);
|
20426
20524
|
setter = getSetter(controller.$name);
|
20427
20525
|
setter(scope, controller);
|
20428
20526
|
});
|
20429
20527
|
}
|
20430
20528
|
formElement.on('$destroy', function() {
|
20431
|
-
|
20529
|
+
controller.$$parentForm.$removeControl(controller);
|
20432
20530
|
setter(scope, undefined);
|
20433
20531
|
extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
|
20434
20532
|
});
|
@@ -20590,9 +20688,17 @@ var inputType = {
|
|
20590
20688
|
* @param {string} ngModel Assignable angular expression to data-bind to.
|
20591
20689
|
* @param {string=} name Property name of the form under which the control is published.
|
20592
20690
|
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
|
20593
|
-
*
|
20691
|
+
* valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute
|
20692
|
+
* (e.g. `min="{{minDate | date:'yyyy-MM-dd'}}"`). Note that `min` will also add native HTML5
|
20693
|
+
* constraint validation.
|
20594
20694
|
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
|
20595
|
-
*
|
20695
|
+
* a valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute
|
20696
|
+
* (e.g. `max="{{maxDate | date:'yyyy-MM-dd'}}"`). Note that `max` will also add native HTML5
|
20697
|
+
* constraint validation.
|
20698
|
+
* @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO date string
|
20699
|
+
* the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
|
20700
|
+
* @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO date string
|
20701
|
+
* the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
|
20596
20702
|
* @param {string=} required Sets `required` validation error key if the value is not entered.
|
20597
20703
|
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
|
20598
20704
|
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
|
@@ -20684,10 +20790,18 @@ var inputType = {
|
|
20684
20790
|
*
|
20685
20791
|
* @param {string} ngModel Assignable angular expression to data-bind to.
|
20686
20792
|
* @param {string=} name Property name of the form under which the control is published.
|
20687
|
-
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
|
20688
|
-
* valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).
|
20689
|
-
*
|
20690
|
-
*
|
20793
|
+
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
|
20794
|
+
* This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation
|
20795
|
+
* inside this attribute (e.g. `min="{{minDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`).
|
20796
|
+
* Note that `min` will also add native HTML5 constraint validation.
|
20797
|
+
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
|
20798
|
+
* This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation
|
20799
|
+
* inside this attribute (e.g. `max="{{maxDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`).
|
20800
|
+
* Note that `max` will also add native HTML5 constraint validation.
|
20801
|
+
* @param {(date|string)=} ngMin Sets the `min` validation error key to the Date / ISO datetime string
|
20802
|
+
* the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
|
20803
|
+
* @param {(date|string)=} ngMax Sets the `max` validation error key to the Date / ISO datetime string
|
20804
|
+
* the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
|
20691
20805
|
* @param {string=} required Sets `required` validation error key if the value is not entered.
|
20692
20806
|
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
|
20693
20807
|
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
|
@@ -20780,10 +20894,18 @@ var inputType = {
|
|
20780
20894
|
*
|
20781
20895
|
* @param {string} ngModel Assignable angular expression to data-bind to.
|
20782
20896
|
* @param {string=} name Property name of the form under which the control is published.
|
20783
|
-
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
|
20784
|
-
* valid ISO time format (HH:mm:ss).
|
20785
|
-
*
|
20786
|
-
*
|
20897
|
+
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
|
20898
|
+
* This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this
|
20899
|
+
* attribute (e.g. `min="{{minTime | date:'HH:mm:ss'}}"`). Note that `min` will also add
|
20900
|
+
* native HTML5 constraint validation.
|
20901
|
+
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
|
20902
|
+
* This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this
|
20903
|
+
* attribute (e.g. `max="{{maxTime | date:'HH:mm:ss'}}"`). Note that `max` will also add
|
20904
|
+
* native HTML5 constraint validation.
|
20905
|
+
* @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO time string the
|
20906
|
+
* `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
|
20907
|
+
* @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO time string the
|
20908
|
+
* `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
|
20787
20909
|
* @param {string=} required Sets `required` validation error key if the value is not entered.
|
20788
20910
|
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
|
20789
20911
|
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
|
@@ -20875,10 +20997,18 @@ var inputType = {
|
|
20875
20997
|
*
|
20876
20998
|
* @param {string} ngModel Assignable angular expression to data-bind to.
|
20877
20999
|
* @param {string=} name Property name of the form under which the control is published.
|
20878
|
-
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
|
20879
|
-
* valid ISO week format (yyyy-W##).
|
20880
|
-
*
|
20881
|
-
*
|
21000
|
+
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
|
21001
|
+
* This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this
|
21002
|
+
* attribute (e.g. `min="{{minWeek | date:'yyyy-Www'}}"`). Note that `min` will also add
|
21003
|
+
* native HTML5 constraint validation.
|
21004
|
+
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
|
21005
|
+
* This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this
|
21006
|
+
* attribute (e.g. `max="{{maxWeek | date:'yyyy-Www'}}"`). Note that `max` will also add
|
21007
|
+
* native HTML5 constraint validation.
|
21008
|
+
* @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string
|
21009
|
+
* the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
|
21010
|
+
* @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string
|
21011
|
+
* the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
|
20882
21012
|
* @param {string=} required Sets `required` validation error key if the value is not entered.
|
20883
21013
|
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
|
20884
21014
|
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
|
@@ -20972,10 +21102,19 @@ var inputType = {
|
|
20972
21102
|
*
|
20973
21103
|
* @param {string} ngModel Assignable angular expression to data-bind to.
|
20974
21104
|
* @param {string=} name Property name of the form under which the control is published.
|
20975
|
-
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
|
20976
|
-
* a valid ISO month format (yyyy-MM).
|
20977
|
-
*
|
20978
|
-
*
|
21105
|
+
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
|
21106
|
+
* This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this
|
21107
|
+
* attribute (e.g. `min="{{minMonth | date:'yyyy-MM'}}"`). Note that `min` will also add
|
21108
|
+
* native HTML5 constraint validation.
|
21109
|
+
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
|
21110
|
+
* This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this
|
21111
|
+
* attribute (e.g. `max="{{maxMonth | date:'yyyy-MM'}}"`). Note that `max` will also add
|
21112
|
+
* native HTML5 constraint validation.
|
21113
|
+
* @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string
|
21114
|
+
* the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
|
21115
|
+
* @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string
|
21116
|
+
* the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
|
21117
|
+
|
20979
21118
|
* @param {string=} required Sets `required` validation error key if the value is not entered.
|
20980
21119
|
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
|
20981
21120
|
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
|
@@ -21737,7 +21876,7 @@ function createDateInputType(type, regexp, parseDate, format) {
|
|
21737
21876
|
}
|
21738
21877
|
|
21739
21878
|
function parseObservedDateValue(val) {
|
21740
|
-
return isDefined(val)
|
21879
|
+
return isDefined(val) && !isDate(val) ? parseDate(val) || undefined : val;
|
21741
21880
|
}
|
21742
21881
|
};
|
21743
21882
|
}
|
@@ -22232,7 +22371,7 @@ var ngBindDirective = ['$compile', function($compile) {
|
|
22232
22371
|
$compile.$$addBindingInfo(element, attr.ngBind);
|
22233
22372
|
element = element[0];
|
22234
22373
|
scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
|
22235
|
-
element.textContent = value
|
22374
|
+
element.textContent = isUndefined(value) ? '' : value;
|
22236
22375
|
});
|
22237
22376
|
};
|
22238
22377
|
}
|
@@ -22300,7 +22439,7 @@ var ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate
|
|
22300
22439
|
$compile.$$addBindingInfo(element, interpolateFn.expressions);
|
22301
22440
|
element = element[0];
|
22302
22441
|
attr.$observe('ngBindTemplate', function(value) {
|
22303
|
-
element.textContent = value
|
22442
|
+
element.textContent = isUndefined(value) ? '' : value;
|
22304
22443
|
});
|
22305
22444
|
};
|
22306
22445
|
}
|
@@ -22717,7 +22856,6 @@ function classDirective(name, selector) {
|
|
22717
22856
|
</file>
|
22718
22857
|
<file name="style.css">
|
22719
22858
|
.base-class {
|
22720
|
-
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
22721
22859
|
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
22722
22860
|
}
|
22723
22861
|
|
@@ -23892,7 +24030,6 @@ forEach(
|
|
23892
24030
|
}
|
23893
24031
|
|
23894
24032
|
.animate-if.ng-enter, .animate-if.ng-leave {
|
23895
|
-
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
23896
24033
|
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
23897
24034
|
}
|
23898
24035
|
|
@@ -24041,7 +24178,6 @@ var ngIfDirective = ['$animate', function($animate) {
|
|
24041
24178
|
}
|
24042
24179
|
|
24043
24180
|
.slide-animate.ng-enter, .slide-animate.ng-leave {
|
24044
|
-
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
24045
24181
|
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
24046
24182
|
|
24047
24183
|
position:absolute;
|
@@ -24260,16 +24396,18 @@ var ngIncludeFillContentDirective = ['$compile',
|
|
24260
24396
|
* current scope.
|
24261
24397
|
*
|
24262
24398
|
* <div class="alert alert-danger">
|
24263
|
-
*
|
24264
|
-
*
|
24265
|
-
*
|
24266
|
-
*
|
24399
|
+
* This directive can be abused to add unnecessary amounts of logic into your templates.
|
24400
|
+
* There are only a few appropriate uses of `ngInit`, such as for aliasing special properties of
|
24401
|
+
* {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below; and for injecting data via
|
24402
|
+
* server side scripting. Besides these few cases, you should use {@link guide/controller controllers}
|
24403
|
+
* rather than `ngInit` to initialize values on a scope.
|
24267
24404
|
* </div>
|
24405
|
+
*
|
24268
24406
|
* <div class="alert alert-warning">
|
24269
|
-
* **Note**: If you have assignment in `ngInit` along with {@link ng.$filter
|
24270
|
-
* sure you have
|
24407
|
+
* **Note**: If you have assignment in `ngInit` along with a {@link ng.$filter `filter`}, make
|
24408
|
+
* sure you have parentheses to ensure correct operator precedence:
|
24271
24409
|
* <pre class="prettyprint">
|
24272
|
-
* `<div ng-init="test1 = (
|
24410
|
+
* `<div ng-init="test1 = ($index | toString)"></div>`
|
24273
24411
|
* </pre>
|
24274
24412
|
* </div>
|
24275
24413
|
*
|
@@ -24382,7 +24520,7 @@ var ngInitDirective = ngDirective({
|
|
24382
24520
|
* </file>
|
24383
24521
|
* </example>
|
24384
24522
|
*
|
24385
|
-
* ### Example - splitting on
|
24523
|
+
* ### Example - splitting on newline
|
24386
24524
|
* <example name="ngList-directive-newlines">
|
24387
24525
|
* <file name="index.html">
|
24388
24526
|
* <textarea ng-model="list" ng-list=" " ng-trim="false"></textarea>
|
@@ -24467,7 +24605,9 @@ var ngModelMinErr = minErr('ngModel');
|
|
24467
24605
|
* @ngdoc type
|
24468
24606
|
* @name ngModel.NgModelController
|
24469
24607
|
*
|
24470
|
-
* @property {
|
24608
|
+
* @property {*} $viewValue The actual value from the control's view. For `input` elements, this is a
|
24609
|
+
* String. See {@link ngModel.NgModelController#$setViewValue} for information about when the $viewValue
|
24610
|
+
* is set.
|
24471
24611
|
* @property {*} $modelValue The value in the model that the control is bound to.
|
24472
24612
|
* @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
|
24473
24613
|
the control reads value from the DOM. The functions are called in array order, each passing
|
@@ -24681,7 +24821,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
24681
24821
|
this.$$success = {}; // keep valid keys here
|
24682
24822
|
this.$pending = undefined; // keep pending keys here
|
24683
24823
|
this.$name = $interpolate($attr.name || '', false)($scope);
|
24684
|
-
|
24824
|
+
this.$$parentForm = nullFormCtrl;
|
24685
24825
|
|
24686
24826
|
var parsedNgModel = $parse($attr.ngModel),
|
24687
24827
|
parsedNgModelAssign = parsedNgModel.assign,
|
@@ -24761,8 +24901,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
24761
24901
|
return isUndefined(value) || value === '' || value === null || value !== value;
|
24762
24902
|
};
|
24763
24903
|
|
24764
|
-
var
|
24765
|
-
currentValidationRunId = 0;
|
24904
|
+
var currentValidationRunId = 0;
|
24766
24905
|
|
24767
24906
|
/**
|
24768
24907
|
* @ngdoc method
|
@@ -24795,7 +24934,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
24795
24934
|
unset: function(object, property) {
|
24796
24935
|
delete object[property];
|
24797
24936
|
},
|
24798
|
-
parentForm: parentForm,
|
24799
24937
|
$animate: $animate
|
24800
24938
|
});
|
24801
24939
|
|
@@ -24833,7 +24971,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
24833
24971
|
ctrl.$pristine = false;
|
24834
24972
|
$animate.removeClass($element, PRISTINE_CLASS);
|
24835
24973
|
$animate.addClass($element, DIRTY_CLASS);
|
24836
|
-
parentForm.$setDirty();
|
24974
|
+
ctrl.$$parentForm.$setDirty();
|
24837
24975
|
};
|
24838
24976
|
|
24839
24977
|
/**
|
@@ -25003,7 +25141,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
25003
25141
|
|
25004
25142
|
function processParseErrors() {
|
25005
25143
|
var errorKey = ctrl.$$parserName || 'parse';
|
25006
|
-
if (parserValid
|
25144
|
+
if (isUndefined(parserValid)) {
|
25007
25145
|
setValidity(errorKey, null);
|
25008
25146
|
} else {
|
25009
25147
|
if (!parserValid) {
|
@@ -25173,37 +25311,47 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
25173
25311
|
* @description
|
25174
25312
|
* Update the view value.
|
25175
25313
|
*
|
25176
|
-
* This method should be called when
|
25177
|
-
* this is done from within a DOM event handler.
|
25178
|
-
*
|
25179
|
-
*
|
25180
|
-
* {@link ng.directive:select select} calls it when an option is selected.
|
25181
|
-
*
|
25182
|
-
* If the new `value` is an object (rather than a string or a number), we should make a copy of the
|
25183
|
-
* object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep
|
25184
|
-
* watch of objects, it only looks for a change of identity. If you only change the property of
|
25185
|
-
* the object then ngModel will not realise that the object has changed and will not invoke the
|
25186
|
-
* `$parsers` and `$validators` pipelines.
|
25187
|
-
*
|
25188
|
-
* For this reason, you should not change properties of the copy once it has been passed to
|
25189
|
-
* `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly.
|
25314
|
+
* This method should be called when a control wants to change the view value; typically,
|
25315
|
+
* this is done from within a DOM event handler. For example, the {@link ng.directive:input input}
|
25316
|
+
* directive calls it when the value of the input changes and {@link ng.directive:select select}
|
25317
|
+
* calls it when an option is selected.
|
25190
25318
|
*
|
25191
|
-
* When
|
25319
|
+
* When `$setViewValue` is called, the new `value` will be staged for committing through the `$parsers`
|
25192
25320
|
* and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged
|
25193
25321
|
* value sent directly for processing, finally to be applied to `$modelValue` and then the
|
25194
|
-
* **expression** specified in the `ng-model` attribute.
|
25195
|
-
*
|
25196
|
-
* Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
|
25322
|
+
* **expression** specified in the `ng-model` attribute. Lastly, all the registered change listeners,
|
25323
|
+
* in the `$viewChangeListeners` list, are called.
|
25197
25324
|
*
|
25198
25325
|
* In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`
|
25199
25326
|
* and the `default` trigger is not listed, all those actions will remain pending until one of the
|
25200
25327
|
* `updateOn` events is triggered on the DOM element.
|
25201
25328
|
* All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}
|
25202
25329
|
* directive is used with a custom debounce for this particular event.
|
25330
|
+
* Note that a `$digest` is only triggered once the `updateOn` events are fired, or if `debounce`
|
25331
|
+
* is specified, once the timer runs out.
|
25332
|
+
*
|
25333
|
+
* When used with standard inputs, the view value will always be a string (which is in some cases
|
25334
|
+
* parsed into another type, such as a `Date` object for `input[date]`.)
|
25335
|
+
* However, custom controls might also pass objects to this method. In this case, we should make
|
25336
|
+
* a copy of the object before passing it to `$setViewValue`. This is because `ngModel` does not
|
25337
|
+
* perform a deep watch of objects, it only looks for a change of identity. If you only change
|
25338
|
+
* the property of the object then ngModel will not realise that the object has changed and
|
25339
|
+
* will not invoke the `$parsers` and `$validators` pipelines. For this reason, you should
|
25340
|
+
* not change properties of the copy once it has been passed to `$setViewValue`.
|
25341
|
+
* Otherwise you may cause the model value on the scope to change incorrectly.
|
25342
|
+
*
|
25343
|
+
* <div class="alert alert-info">
|
25344
|
+
* In any case, the value passed to the method should always reflect the current value
|
25345
|
+
* of the control. For example, if you are calling `$setViewValue` for an input element,
|
25346
|
+
* you should pass the input DOM value. Otherwise, the control and the scope model become
|
25347
|
+
* out of sync. It's also important to note that `$setViewValue` does not call `$render` or change
|
25348
|
+
* the control's DOM value in any way. If we want to change the control's DOM value
|
25349
|
+
* programmatically, we should update the `ngModel` scope expression. Its new value will be
|
25350
|
+
* picked up by the model controller, which will run it through the `$formatters`, `$render` it
|
25351
|
+
* to update the DOM, and finally call `$validate` on it.
|
25352
|
+
* </div>
|
25203
25353
|
*
|
25204
|
-
*
|
25205
|
-
*
|
25206
|
-
* @param {string} value Value from the view.
|
25354
|
+
* @param {*} value value from the view.
|
25207
25355
|
* @param {string} trigger Event that triggered the update.
|
25208
25356
|
*/
|
25209
25357
|
this.$setViewValue = function(value, trigger) {
|
@@ -25380,7 +25528,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
25380
25528
|
</script>
|
25381
25529
|
<style>
|
25382
25530
|
.my-input {
|
25383
|
-
-webkit-transition:all linear 0.5s;
|
25384
25531
|
transition:all linear 0.5s;
|
25385
25532
|
background: transparent;
|
25386
25533
|
}
|
@@ -25467,7 +25614,7 @@ var ngModelDirective = ['$rootScope', function($rootScope) {
|
|
25467
25614
|
return {
|
25468
25615
|
pre: function ngModelPreLink(scope, element, attr, ctrls) {
|
25469
25616
|
var modelCtrl = ctrls[0],
|
25470
|
-
formCtrl = ctrls[1] ||
|
25617
|
+
formCtrl = ctrls[1] || modelCtrl.$$parentForm;
|
25471
25618
|
|
25472
25619
|
modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);
|
25473
25620
|
|
@@ -25476,12 +25623,12 @@ var ngModelDirective = ['$rootScope', function($rootScope) {
|
|
25476
25623
|
|
25477
25624
|
attr.$observe('name', function(newValue) {
|
25478
25625
|
if (modelCtrl.$name !== newValue) {
|
25479
|
-
|
25626
|
+
modelCtrl.$$parentForm.$$renameControl(modelCtrl, newValue);
|
25480
25627
|
}
|
25481
25628
|
});
|
25482
25629
|
|
25483
25630
|
scope.$on('$destroy', function() {
|
25484
|
-
|
25631
|
+
modelCtrl.$$parentForm.$removeControl(modelCtrl);
|
25485
25632
|
});
|
25486
25633
|
},
|
25487
25634
|
post: function ngModelPostLink(scope, element, attr, ctrls) {
|
@@ -25676,7 +25823,7 @@ var ngModelOptionsDirective = function() {
|
|
25676
25823
|
var that = this;
|
25677
25824
|
this.$options = copy($scope.$eval($attrs.ngModelOptions));
|
25678
25825
|
// Allow adding/overriding bound events
|
25679
|
-
if (this.$options.updateOn
|
25826
|
+
if (isDefined(this.$options.updateOn)) {
|
25680
25827
|
this.$options.updateOnDefault = false;
|
25681
25828
|
// extract "default" pseudo-event from list of events that can trigger a model update
|
25682
25829
|
this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() {
|
@@ -25699,7 +25846,6 @@ function addSetValidityMethod(context) {
|
|
25699
25846
|
classCache = {},
|
25700
25847
|
set = context.set,
|
25701
25848
|
unset = context.unset,
|
25702
|
-
parentForm = context.parentForm,
|
25703
25849
|
$animate = context.$animate;
|
25704
25850
|
|
25705
25851
|
classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS));
|
@@ -25707,7 +25853,7 @@ function addSetValidityMethod(context) {
|
|
25707
25853
|
ctrl.$setValidity = setValidity;
|
25708
25854
|
|
25709
25855
|
function setValidity(validationErrorKey, state, controller) {
|
25710
|
-
if (state
|
25856
|
+
if (isUndefined(state)) {
|
25711
25857
|
createAndSet('$pending', validationErrorKey, controller);
|
25712
25858
|
} else {
|
25713
25859
|
unsetAndCleanup('$pending', validationErrorKey, controller);
|
@@ -25751,7 +25897,7 @@ function addSetValidityMethod(context) {
|
|
25751
25897
|
}
|
25752
25898
|
|
25753
25899
|
toggleValidationCss(validationErrorKey, combinedState);
|
25754
|
-
parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
|
25900
|
+
ctrl.$$parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
|
25755
25901
|
}
|
25756
25902
|
|
25757
25903
|
function createAndSet(name, value, controller) {
|
@@ -26412,11 +26558,16 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
26412
26558
|
function updateOptionElement(option, element) {
|
26413
26559
|
option.element = element;
|
26414
26560
|
element.disabled = option.disabled;
|
26415
|
-
|
26561
|
+
// NOTE: The label must be set before the value, otherwise IE10/11/EDGE create unresponsive
|
26562
|
+
// selects in certain circumstances when multiple selects are next to each other and display
|
26563
|
+
// the option list in listbox style, i.e. the select is [multiple], or specifies a [size].
|
26564
|
+
// See https://github.com/angular/angular.js/issues/11314 for more info.
|
26565
|
+
// This is unfortunately untestable with unit / e2e tests
|
26416
26566
|
if (option.label !== element.label) {
|
26417
26567
|
element.label = option.label;
|
26418
26568
|
element.textContent = option.label;
|
26419
26569
|
}
|
26570
|
+
if (option.value !== element.value) element.value = option.selectValue;
|
26420
26571
|
}
|
26421
26572
|
|
26422
26573
|
function addOrReuseElement(parent, current, type, templateElement) {
|
@@ -26457,7 +26608,10 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
26457
26608
|
if (emptyOption_ || unknownOption_) {
|
26458
26609
|
while (current &&
|
26459
26610
|
(current === emptyOption_ ||
|
26460
|
-
current === unknownOption_
|
26611
|
+
current === unknownOption_ ||
|
26612
|
+
emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) {
|
26613
|
+
// Empty options might have directives that transclude
|
26614
|
+
// and insert comments (e.g. ngIf)
|
26461
26615
|
current = current.nextSibling;
|
26462
26616
|
}
|
26463
26617
|
}
|
@@ -26819,8 +26973,10 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
|
|
26819
26973
|
* | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). |
|
26820
26974
|
* | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). |
|
26821
26975
|
*
|
26822
|
-
*
|
26823
|
-
*
|
26976
|
+
* <div class="alert alert-info">
|
26977
|
+
* Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.
|
26978
|
+
* This may be useful when, for instance, nesting ngRepeats.
|
26979
|
+
* </div>
|
26824
26980
|
*
|
26825
26981
|
*
|
26826
26982
|
* # Iterating over object properties
|
@@ -27054,7 +27210,6 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
|
|
27054
27210
|
.animate-repeat.ng-move,
|
27055
27211
|
.animate-repeat.ng-enter,
|
27056
27212
|
.animate-repeat.ng-leave {
|
27057
|
-
-webkit-transition:all linear 0.5s;
|
27058
27213
|
transition:all linear 0.5s;
|
27059
27214
|
}
|
27060
27215
|
|
@@ -27226,7 +27381,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
|
|
27226
27381
|
// if object, extract keys, in enumeration order, unsorted
|
27227
27382
|
collectionKeys = [];
|
27228
27383
|
for (var itemKey in collection) {
|
27229
|
-
if (
|
27384
|
+
if (hasOwnProperty.call(collection, itemKey) && itemKey.charAt(0) !== '$') {
|
27230
27385
|
collectionKeys.push(itemKey);
|
27231
27386
|
}
|
27232
27387
|
}
|
@@ -27451,9 +27606,7 @@ var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
|
|
27451
27606
|
background: white;
|
27452
27607
|
}
|
27453
27608
|
|
27454
|
-
.animate-show.ng-hide-add.ng-hide-
|
27455
|
-
.animate-show.ng-hide-remove.ng-hide-remove-active {
|
27456
|
-
-webkit-transition: all linear 0.5s;
|
27609
|
+
.animate-show.ng-hide-add, .animate-show.ng-hide-remove {
|
27457
27610
|
transition: all linear 0.5s;
|
27458
27611
|
}
|
27459
27612
|
|
@@ -27610,7 +27763,6 @@ var ngShowDirective = ['$animate', function($animate) {
|
|
27610
27763
|
</file>
|
27611
27764
|
<file name="animations.css">
|
27612
27765
|
.animate-hide {
|
27613
|
-
-webkit-transition: all linear 0.5s;
|
27614
27766
|
transition: all linear 0.5s;
|
27615
27767
|
line-height: 20px;
|
27616
27768
|
opacity: 1;
|
@@ -27809,7 +27961,6 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
|
|
27809
27961
|
}
|
27810
27962
|
|
27811
27963
|
.animate-switch.ng-animate {
|
27812
|
-
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
27813
27964
|
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
27814
27965
|
|
27815
27966
|
position:absolute;
|
@@ -28150,31 +28301,162 @@ var SelectController =
|
|
28150
28301
|
* @description
|
28151
28302
|
* HTML `SELECT` element with angular data-binding.
|
28152
28303
|
*
|
28153
|
-
*
|
28154
|
-
*
|
28155
|
-
*
|
28156
|
-
*
|
28157
|
-
* comprehension expression.
|
28304
|
+
* The `select` directive is used together with {@link ngModel `ngModel`} to provide data-binding
|
28305
|
+
* between the scope and the `<select>` control (including setting default values).
|
28306
|
+
* Ìt also handles dynamic `<option>` elements, which can be added using the {@link ngRepeat `ngRepeat}` or
|
28307
|
+
* {@link ngOptions `ngOptions`} directives.
|
28158
28308
|
*
|
28159
|
-
* When an item in the `<select>` menu is selected, the
|
28160
|
-
*
|
28161
|
-
*
|
28309
|
+
* When an item in the `<select>` menu is selected, the value of the selected option will be bound
|
28310
|
+
* to the model identified by the `ngModel` directive. With static or repeated options, this is
|
28311
|
+
* the content of the `value` attribute or the textContent of the `<option>`, if the value attribute is missing.
|
28312
|
+
* If you want dynamic value attributes, you can use interpolation inside the value attribute.
|
28162
28313
|
*
|
28163
|
-
*
|
28164
|
-
*
|
28314
|
+
* <div class="alert alert-warning">
|
28315
|
+
* Note that the value of a `select` directive used without `ngOptions` is always a string.
|
28316
|
+
* When the model needs to be bound to a non-string value, you must either explictly convert it
|
28317
|
+
* using a directive (see example below) or use `ngOptions` to specify the set of options.
|
28318
|
+
* This is because an option element can only be bound to string values at present.
|
28319
|
+
* </div>
|
28320
|
+
*
|
28321
|
+
* If the viewValue of `ngModel` does not match any of the options, then the control
|
28322
|
+
* will automatically add an "unknown" option, which it then removes when the mismatch is resolved.
|
28165
28323
|
*
|
28166
28324
|
* Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
|
28167
28325
|
* be nested into the `<select>` element. This element will then represent the `null` or "not selected"
|
28168
28326
|
* option. See example below for demonstration.
|
28169
28327
|
*
|
28170
28328
|
* <div class="alert alert-info">
|
28171
|
-
*
|
28172
|
-
*
|
28173
|
-
*
|
28174
|
-
*
|
28329
|
+
* In many cases, `ngRepeat` can be used on `<option>` elements instead of {@link ng.directive:ngOptions
|
28330
|
+
* ngOptions} to achieve a similar result. However, `ngOptions` provides some benefits, such as
|
28331
|
+
* more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
|
28332
|
+
* comprehension expression, and additionally in reducing memory and increasing speed by not creating
|
28333
|
+
* a new scope for each repeated instance.
|
28334
|
+
* </div>
|
28335
|
+
*
|
28336
|
+
*
|
28337
|
+
* @param {string} ngModel Assignable angular expression to data-bind to.
|
28338
|
+
* @param {string=} name Property name of the form under which the control is published.
|
28339
|
+
* @param {string=} required Sets `required` validation error key if the value is not entered.
|
28340
|
+
* @param {string=} ngRequired Adds required attribute and required validation constraint to
|
28341
|
+
* the element when the ngRequired expression evaluates to true. Use ngRequired instead of required
|
28342
|
+
* when you want to data-bind to the required attribute.
|
28343
|
+
* @param {string=} ngChange Angular expression to be executed when selected option(s) changes due to user
|
28344
|
+
* interaction with the select element.
|
28345
|
+
* @param {string=} ngOptions sets the options that the select is populated with and defines what is
|
28346
|
+
* set on the model on selection. See {@link ngOptions `ngOptions`}.
|
28347
|
+
*
|
28348
|
+
* @example
|
28349
|
+
* ### Simple `select` elements with static options
|
28350
|
+
*
|
28351
|
+
* <example name="static-select" module="staticSelect">
|
28352
|
+
* <file name="index.html">
|
28353
|
+
* <div ng-controller="ExampleController">
|
28354
|
+
* <form name="myForm">
|
28355
|
+
* <label for="singleSelect"> Single select: </label><br>
|
28356
|
+
* <select name="singleSelect" ng-model="data.singleSelect">
|
28357
|
+
* <option value="option-1">Option 1</option>
|
28358
|
+
* <option value="option-2">Option 2</option>
|
28359
|
+
* </select><br>
|
28360
|
+
*
|
28361
|
+
* <label for="singleSelect"> Single select with "not selected" option and dynamic option values: </label><br>
|
28362
|
+
* <select name="singleSelect" id="singleSelect" ng-model="data.singleSelect">
|
28363
|
+
* <option value="">---Please select---</option> <!-- not selected / blank option -->
|
28364
|
+
* <option value="{{data.option1}}">Option 1</option> <!-- interpolation -->
|
28365
|
+
* <option value="option-2">Option 2</option>
|
28366
|
+
* </select><br>
|
28367
|
+
* <button ng-click="forceUnknownOption()">Force unknown option</button><br>
|
28368
|
+
* <tt>singleSelect = {{data.singleSelect}}</tt>
|
28369
|
+
*
|
28370
|
+
* <hr>
|
28371
|
+
* <label for="multipleSelect"> Multiple select: </label><br>
|
28372
|
+
* <select name="multipleSelect" id="multipleSelect" ng-model="data.multipleSelect" multiple>
|
28373
|
+
* <option value="option-1">Option 1</option>
|
28374
|
+
* <option value="option-2">Option 2</option>
|
28375
|
+
* <option value="option-3">Option 3</option>
|
28376
|
+
* </select><br>
|
28377
|
+
* <tt>multipleSelect = {{data.multipleSelect}}</tt><br/>
|
28378
|
+
* </form>
|
28379
|
+
* </div>
|
28380
|
+
* </file>
|
28381
|
+
* <file name="app.js">
|
28382
|
+
* angular.module('staticSelect', [])
|
28383
|
+
* .controller('ExampleController', ['$scope', function($scope) {
|
28384
|
+
* $scope.data = {
|
28385
|
+
* singleSelect: null,
|
28386
|
+
* multipleSelect: [],
|
28387
|
+
* option1: 'option-1',
|
28388
|
+
* };
|
28389
|
+
*
|
28390
|
+
* $scope.forceUnknownOption = function() {
|
28391
|
+
* $scope.data.singleSelect = 'nonsense';
|
28392
|
+
* };
|
28393
|
+
* }]);
|
28394
|
+
* </file>
|
28395
|
+
*</example>
|
28396
|
+
*
|
28397
|
+
* ### Using `ngRepeat` to generate `select` options
|
28398
|
+
* <example name="ngrepeat-select" module="ngrepeatSelect">
|
28399
|
+
* <file name="index.html">
|
28400
|
+
* <div ng-controller="ExampleController">
|
28401
|
+
* <form name="myForm">
|
28402
|
+
* <label for="repeatSelect"> Repeat select: </label>
|
28403
|
+
* <select name="repeatSelect" id="repeatSelect" ng-model="data.repeatSelect">
|
28404
|
+
* <option ng-repeat="option in data.availableOptions" value="{{option.id}}">{{option.name}}</option>
|
28405
|
+
* </select>
|
28406
|
+
* </form>
|
28407
|
+
* <hr>
|
28408
|
+
* <tt>repeatSelect = {{data.repeatSelect}}</tt><br/>
|
28175
28409
|
* </div>
|
28410
|
+
* </file>
|
28411
|
+
* <file name="app.js">
|
28412
|
+
* angular.module('ngrepeatSelect', [])
|
28413
|
+
* .controller('ExampleController', ['$scope', function($scope) {
|
28414
|
+
* $scope.data = {
|
28415
|
+
* repeatSelect: null,
|
28416
|
+
* availableOptions: [
|
28417
|
+
* {id: '1', name: 'Option A'},
|
28418
|
+
* {id: '2', name: 'Option B'},
|
28419
|
+
* {id: '3', name: 'Option C'}
|
28420
|
+
* ],
|
28421
|
+
* };
|
28422
|
+
* }]);
|
28423
|
+
* </file>
|
28424
|
+
*</example>
|
28176
28425
|
*
|
28177
|
-
*
|
28426
|
+
*
|
28427
|
+
* ### Using `select` with `ngOptions` and setting a default value
|
28428
|
+
* See the {@link ngOptions ngOptions documentation} for more `ngOptions` usage examples.
|
28429
|
+
*
|
28430
|
+
* <example name="select-with-default-values" module="defaultValueSelect">
|
28431
|
+
* <file name="index.html">
|
28432
|
+
* <div ng-controller="ExampleController">
|
28433
|
+
* <form name="myForm">
|
28434
|
+
* <label for="mySelect">Make a choice:</label>
|
28435
|
+
* <select name="mySelect" id="mySelect"
|
28436
|
+
* ng-options="option.name for option in data.availableOptions track by option.id"
|
28437
|
+
* ng-model="data.selectedOption"></select>
|
28438
|
+
* </form>
|
28439
|
+
* <hr>
|
28440
|
+
* <tt>option = {{data.selectedOption}}</tt><br/>
|
28441
|
+
* </div>
|
28442
|
+
* </file>
|
28443
|
+
* <file name="app.js">
|
28444
|
+
* angular.module('defaultValueSelect', [])
|
28445
|
+
* .controller('ExampleController', ['$scope', function($scope) {
|
28446
|
+
* $scope.data = {
|
28447
|
+
* availableOptions: [
|
28448
|
+
* {id: '1', name: 'Option A'},
|
28449
|
+
* {id: '2', name: 'Option B'},
|
28450
|
+
* {id: '3', name: 'Option C'}
|
28451
|
+
* ],
|
28452
|
+
* selectedOption: {id: '3', name: 'Option C'} //This sets the default value of the select in the ui
|
28453
|
+
* };
|
28454
|
+
* }]);
|
28455
|
+
* </file>
|
28456
|
+
*</example>
|
28457
|
+
*
|
28458
|
+
*
|
28459
|
+
* ### Binding `select` to a non-string value via `ngModel` parsing / formatting
|
28178
28460
|
*
|
28179
28461
|
* <example name="select-with-non-string-options" module="nonStringSelect">
|
28180
28462
|
* <file name="index.html">
|
@@ -28312,9 +28594,12 @@ var optionDirective = ['$interpolate', function($interpolate) {
|
|
28312
28594
|
priority: 100,
|
28313
28595
|
compile: function(element, attr) {
|
28314
28596
|
|
28315
|
-
|
28316
|
-
|
28317
|
-
|
28597
|
+
if (isDefined(attr.value)) {
|
28598
|
+
// If the value attribute is defined, check if it contains an interpolation
|
28599
|
+
var valueInterpolated = $interpolate(attr.value, true);
|
28600
|
+
} else {
|
28601
|
+
// If the value attribute is not defined then we fall back to the
|
28602
|
+
// text content of the option element, which may be interpolated
|
28318
28603
|
var interpolateFn = $interpolate(element.text(), true);
|
28319
28604
|
if (!interpolateFn) {
|
28320
28605
|
attr.$set('value', element.text());
|
@@ -28330,24 +28615,38 @@ var optionDirective = ['$interpolate', function($interpolate) {
|
|
28330
28615
|
selectCtrl = parent.data(selectCtrlName) ||
|
28331
28616
|
parent.parent().data(selectCtrlName); // in case we are in optgroup
|
28332
28617
|
|
28618
|
+
function addOption(optionValue) {
|
28619
|
+
selectCtrl.addOption(optionValue, element);
|
28620
|
+
selectCtrl.ngModelCtrl.$render();
|
28621
|
+
chromeHack(element);
|
28622
|
+
}
|
28623
|
+
|
28333
28624
|
// Only update trigger option updates if this is an option within a `select`
|
28334
28625
|
// that also has `ngModel` attached
|
28335
28626
|
if (selectCtrl && selectCtrl.ngModelCtrl) {
|
28336
28627
|
|
28337
|
-
if (
|
28628
|
+
if (valueInterpolated) {
|
28629
|
+
// The value attribute is interpolated
|
28630
|
+
var oldVal;
|
28631
|
+
attr.$observe('value', function valueAttributeObserveAction(newVal) {
|
28632
|
+
if (isDefined(oldVal)) {
|
28633
|
+
selectCtrl.removeOption(oldVal);
|
28634
|
+
}
|
28635
|
+
oldVal = newVal;
|
28636
|
+
addOption(newVal);
|
28637
|
+
});
|
28638
|
+
} else if (interpolateFn) {
|
28639
|
+
// The text content is interpolated
|
28338
28640
|
scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
|
28339
28641
|
attr.$set('value', newVal);
|
28340
28642
|
if (oldVal !== newVal) {
|
28341
28643
|
selectCtrl.removeOption(oldVal);
|
28342
28644
|
}
|
28343
|
-
|
28344
|
-
selectCtrl.ngModelCtrl.$render();
|
28345
|
-
chromeHack(element);
|
28645
|
+
addOption(newVal);
|
28346
28646
|
});
|
28347
28647
|
} else {
|
28348
|
-
|
28349
|
-
|
28350
|
-
chromeHack(element);
|
28648
|
+
// The value attribute is static
|
28649
|
+
addOption(attr.value);
|
28351
28650
|
}
|
28352
28651
|
|
28353
28652
|
element.on('$destroy', function() {
|
@@ -28408,8 +28707,9 @@ var patternDirective = function() {
|
|
28408
28707
|
ctrl.$validate();
|
28409
28708
|
});
|
28410
28709
|
|
28411
|
-
ctrl.$validators.pattern = function(
|
28412
|
-
|
28710
|
+
ctrl.$validators.pattern = function(modelValue, viewValue) {
|
28711
|
+
// HTML5 pattern constraint validates the input value, so we validate the viewValue
|
28712
|
+
return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue);
|
28413
28713
|
};
|
28414
28714
|
}
|
28415
28715
|
};
|