angularjs-rails 1.4.7 → 1.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/angularjs-rails/version.rb +2 -2
- data/vendor/assets/javascripts/angular-animate.js +19 -17
- data/vendor/assets/javascripts/angular-aria.js +3 -2
- data/vendor/assets/javascripts/angular-cookies.js +1 -1
- data/vendor/assets/javascripts/angular-loader.js +3 -3
- data/vendor/assets/javascripts/angular-message-format.js +1 -1
- data/vendor/assets/javascripts/angular-messages.js +1 -1
- data/vendor/assets/javascripts/angular-mocks.js +4 -3
- data/vendor/assets/javascripts/angular-resource.js +12 -3
- data/vendor/assets/javascripts/angular-route.js +1 -1
- data/vendor/assets/javascripts/angular-sanitize.js +1 -1
- data/vendor/assets/javascripts/angular-scenario.js +470 -355
- data/vendor/assets/javascripts/angular-touch.js +1 -1
- data/vendor/assets/javascripts/angular.js +468 -354
- data/vendor/assets/javascripts/unstable/angular2.js +26732 -26775
- metadata +2 -2
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.4.
|
2
|
+
* @license AngularJS v1.4.8
|
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.8/' +
|
61
61
|
(module ? module + '/' : '') + code;
|
62
62
|
|
63
63
|
for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
|
@@ -267,20 +267,24 @@ msie = document.documentMode;
|
|
267
267
|
* String ...)
|
268
268
|
*/
|
269
269
|
function isArrayLike(obj) {
|
270
|
-
|
271
|
-
|
272
|
-
|
270
|
+
|
271
|
+
// `null`, `undefined` and `window` are not array-like
|
272
|
+
if (obj == null || isWindow(obj)) return false;
|
273
|
+
|
274
|
+
// arrays, strings and jQuery/jqLite objects are array like
|
275
|
+
// * jqLite is either the jQuery or jqLite constructor function
|
276
|
+
// * we have to check the existance of jqLite first as this method is called
|
277
|
+
// via the forEach method when constructing the jqLite object in the first place
|
278
|
+
if (isArray(obj) || isString(obj) || (jqLite && obj instanceof jqLite)) return true;
|
273
279
|
|
274
280
|
// Support: iOS 8.2 (not reproducible in simulator)
|
275
281
|
// "length" in obj used to prevent JIT error (gh-11508)
|
276
282
|
var length = "length" in Object(obj) && obj.length;
|
277
283
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
return isString(obj) || isArray(obj) || length === 0 ||
|
283
|
-
typeof length === 'number' && length > 0 && (length - 1) in obj;
|
284
|
+
// NodeList objects (with `item` method) and
|
285
|
+
// other objects with suitable length characteristics are array-like
|
286
|
+
return isNumber(length) &&
|
287
|
+
(length >= 0 && (length - 1) in obj || typeof obj.item == 'function');
|
284
288
|
}
|
285
289
|
|
286
290
|
/**
|
@@ -425,6 +429,10 @@ function baseExtend(dst, objs, deep) {
|
|
425
429
|
dst[key] = new Date(src.valueOf());
|
426
430
|
} else if (isRegExp(src)) {
|
427
431
|
dst[key] = new RegExp(src);
|
432
|
+
} else if (src.nodeName) {
|
433
|
+
dst[key] = src.cloneNode(true);
|
434
|
+
} else if (isElement(src)) {
|
435
|
+
dst[key] = src.clone();
|
428
436
|
} else {
|
429
437
|
if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
|
430
438
|
baseExtend(dst[key], [src], true);
|
@@ -540,7 +548,7 @@ identity.$inject = [];
|
|
540
548
|
function valueFn(value) {return function() {return value;};}
|
541
549
|
|
542
550
|
function hasCustomToString(obj) {
|
543
|
-
return isFunction(obj.toString) && obj.toString !==
|
551
|
+
return isFunction(obj.toString) && obj.toString !== toString;
|
544
552
|
}
|
545
553
|
|
546
554
|
|
@@ -739,9 +747,9 @@ function isPromiseLike(obj) {
|
|
739
747
|
}
|
740
748
|
|
741
749
|
|
742
|
-
var TYPED_ARRAY_REGEXP = /^\[object (Uint8
|
750
|
+
var TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/;
|
743
751
|
function isTypedArray(value) {
|
744
|
-
return TYPED_ARRAY_REGEXP.test(toString.call(value));
|
752
|
+
return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value));
|
745
753
|
}
|
746
754
|
|
747
755
|
|
@@ -863,100 +871,111 @@ function arrayRemove(array, value) {
|
|
863
871
|
</file>
|
864
872
|
</example>
|
865
873
|
*/
|
866
|
-
function copy(source, destination
|
867
|
-
|
868
|
-
|
869
|
-
"Can't copy! Making copies of Window or Scope instances is not supported.");
|
870
|
-
}
|
871
|
-
if (isTypedArray(destination)) {
|
872
|
-
throw ngMinErr('cpta',
|
873
|
-
"Can't copy! TypedArray destination cannot be mutated.");
|
874
|
-
}
|
874
|
+
function copy(source, destination) {
|
875
|
+
var stackSource = [];
|
876
|
+
var stackDest = [];
|
875
877
|
|
876
|
-
if (
|
877
|
-
destination
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
// TypedArray, Date and RegExp have specific copy functionality and must be
|
885
|
-
// pushed onto the stack before returning.
|
886
|
-
// Array and other objects create the base object and recurse to copy child
|
887
|
-
// objects. The array/object will be pushed onto the stack when recursed.
|
888
|
-
if (isArray(source)) {
|
889
|
-
return copy(source, [], stackSource, stackDest);
|
890
|
-
} else if (isTypedArray(source)) {
|
891
|
-
destination = new source.constructor(source);
|
892
|
-
} else if (isDate(source)) {
|
893
|
-
destination = new Date(source.getTime());
|
894
|
-
} else if (isRegExp(source)) {
|
895
|
-
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
|
896
|
-
destination.lastIndex = source.lastIndex;
|
897
|
-
} else if (isFunction(source.cloneNode)) {
|
898
|
-
destination = source.cloneNode(true);
|
899
|
-
} else {
|
900
|
-
var emptyObject = Object.create(getPrototypeOf(source));
|
901
|
-
return copy(source, emptyObject, stackSource, stackDest);
|
902
|
-
}
|
878
|
+
if (destination) {
|
879
|
+
if (isTypedArray(destination)) {
|
880
|
+
throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated.");
|
881
|
+
}
|
882
|
+
if (source === destination) {
|
883
|
+
throw ngMinErr('cpi', "Can't copy! Source and destination are identical.");
|
884
|
+
}
|
903
885
|
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
886
|
+
// Empty the destination object
|
887
|
+
if (isArray(destination)) {
|
888
|
+
destination.length = 0;
|
889
|
+
} else {
|
890
|
+
forEach(destination, function(value, key) {
|
891
|
+
if (key !== '$$hashKey') {
|
892
|
+
delete destination[key];
|
893
|
+
}
|
894
|
+
});
|
908
895
|
}
|
909
|
-
} else {
|
910
|
-
if (source === destination) throw ngMinErr('cpi',
|
911
|
-
"Can't copy! Source and destination are identical.");
|
912
896
|
|
913
|
-
stackSource
|
914
|
-
stackDest
|
897
|
+
stackSource.push(source);
|
898
|
+
stackDest.push(destination);
|
899
|
+
return copyRecurse(source, destination);
|
900
|
+
}
|
915
901
|
|
916
|
-
|
917
|
-
stackSource.push(source);
|
918
|
-
stackDest.push(destination);
|
919
|
-
}
|
902
|
+
return copyElement(source);
|
920
903
|
|
904
|
+
function copyRecurse(source, destination) {
|
905
|
+
var h = destination.$$hashKey;
|
921
906
|
var result, key;
|
922
907
|
if (isArray(source)) {
|
923
|
-
|
924
|
-
|
925
|
-
destination.push(copy(source[i], null, stackSource, stackDest));
|
908
|
+
for (var i = 0, ii = source.length; i < ii; i++) {
|
909
|
+
destination.push(copyElement(source[i]));
|
926
910
|
}
|
927
|
-
} else {
|
928
|
-
|
929
|
-
|
930
|
-
destination
|
931
|
-
}
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
// createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
|
938
|
-
for (key in source) {
|
939
|
-
destination[key] = copy(source[key], null, stackSource, stackDest);
|
940
|
-
}
|
941
|
-
} else if (source && typeof source.hasOwnProperty === 'function') {
|
942
|
-
// Slow path, which must rely on hasOwnProperty
|
943
|
-
for (key in source) {
|
944
|
-
if (source.hasOwnProperty(key)) {
|
945
|
-
destination[key] = copy(source[key], null, stackSource, stackDest);
|
946
|
-
}
|
911
|
+
} else if (isBlankObject(source)) {
|
912
|
+
// createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
|
913
|
+
for (key in source) {
|
914
|
+
destination[key] = copyElement(source[key]);
|
915
|
+
}
|
916
|
+
} else if (source && typeof source.hasOwnProperty === 'function') {
|
917
|
+
// Slow path, which must rely on hasOwnProperty
|
918
|
+
for (key in source) {
|
919
|
+
if (source.hasOwnProperty(key)) {
|
920
|
+
destination[key] = copyElement(source[key]);
|
947
921
|
}
|
948
|
-
}
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
922
|
+
}
|
923
|
+
} else {
|
924
|
+
// Slowest path --- hasOwnProperty can't be called as a method
|
925
|
+
for (key in source) {
|
926
|
+
if (hasOwnProperty.call(source, key)) {
|
927
|
+
destination[key] = copyElement(source[key]);
|
954
928
|
}
|
955
929
|
}
|
956
|
-
setHashKey(destination,h);
|
957
930
|
}
|
931
|
+
setHashKey(destination, h);
|
932
|
+
return destination;
|
933
|
+
}
|
934
|
+
|
935
|
+
function copyElement(source) {
|
936
|
+
// Simple values
|
937
|
+
if (!isObject(source)) {
|
938
|
+
return source;
|
939
|
+
}
|
940
|
+
|
941
|
+
// Already copied values
|
942
|
+
var index = stackSource.indexOf(source);
|
943
|
+
if (index !== -1) {
|
944
|
+
return stackDest[index];
|
945
|
+
}
|
946
|
+
|
947
|
+
if (isWindow(source) || isScope(source)) {
|
948
|
+
throw ngMinErr('cpws',
|
949
|
+
"Can't copy! Making copies of Window or Scope instances is not supported.");
|
950
|
+
}
|
951
|
+
|
952
|
+
var needsRecurse = false;
|
953
|
+
var destination;
|
954
|
+
|
955
|
+
if (isArray(source)) {
|
956
|
+
destination = [];
|
957
|
+
needsRecurse = true;
|
958
|
+
} else if (isTypedArray(source)) {
|
959
|
+
destination = new source.constructor(source);
|
960
|
+
} else if (isDate(source)) {
|
961
|
+
destination = new Date(source.getTime());
|
962
|
+
} else if (isRegExp(source)) {
|
963
|
+
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
|
964
|
+
destination.lastIndex = source.lastIndex;
|
965
|
+
} else if (isFunction(source.cloneNode)) {
|
966
|
+
destination = source.cloneNode(true);
|
967
|
+
} else {
|
968
|
+
destination = Object.create(getPrototypeOf(source));
|
969
|
+
needsRecurse = true;
|
970
|
+
}
|
971
|
+
|
972
|
+
stackSource.push(source);
|
973
|
+
stackDest.push(destination);
|
974
|
+
|
975
|
+
return needsRecurse
|
976
|
+
? copyRecurse(source, destination)
|
977
|
+
: destination;
|
958
978
|
}
|
959
|
-
return destination;
|
960
979
|
}
|
961
980
|
|
962
981
|
/**
|
@@ -2080,7 +2099,7 @@ function setupModuleLoader(window) {
|
|
2080
2099
|
* @param {string} name constant name
|
2081
2100
|
* @param {*} object Constant value.
|
2082
2101
|
* @description
|
2083
|
-
* Because the
|
2102
|
+
* Because the constants are fixed, they get applied before other provide methods.
|
2084
2103
|
* See {@link auto.$provide#constant $provide.constant()}.
|
2085
2104
|
*/
|
2086
2105
|
constant: invokeLater('$provide', 'constant', 'unshift'),
|
@@ -2379,11 +2398,11 @@ function toDebugString(obj) {
|
|
2379
2398
|
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
|
2380
2399
|
*/
|
2381
2400
|
var version = {
|
2382
|
-
full: '1.4.
|
2401
|
+
full: '1.4.8', // all of these placeholder strings will be replaced by grunt's
|
2383
2402
|
major: 1, // package task
|
2384
2403
|
minor: 4,
|
2385
|
-
dot:
|
2386
|
-
codeName: '
|
2404
|
+
dot: 8,
|
2405
|
+
codeName: 'ice-manipulation'
|
2387
2406
|
};
|
2388
2407
|
|
2389
2408
|
|
@@ -2765,6 +2784,14 @@ function jqLiteParseHTML(html, context) {
|
|
2765
2784
|
return [];
|
2766
2785
|
}
|
2767
2786
|
|
2787
|
+
|
2788
|
+
// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
|
2789
|
+
var jqLiteContains = Node.prototype.contains || function(arg) {
|
2790
|
+
// jshint bitwise: false
|
2791
|
+
return !!(this.compareDocumentPosition(arg) & 16);
|
2792
|
+
// jshint bitwise: true
|
2793
|
+
};
|
2794
|
+
|
2768
2795
|
/////////////////////////////////////////////
|
2769
2796
|
function JQLite(element) {
|
2770
2797
|
if (element instanceof JQLite) {
|
@@ -2823,17 +2850,23 @@ function jqLiteOff(element, type, fn, unsupported) {
|
|
2823
2850
|
delete events[type];
|
2824
2851
|
}
|
2825
2852
|
} else {
|
2826
|
-
|
2853
|
+
|
2854
|
+
var removeHandler = function(type) {
|
2855
|
+
var listenerFns = events[type];
|
2827
2856
|
if (isDefined(fn)) {
|
2828
|
-
var listenerFns = events[type];
|
2829
2857
|
arrayRemove(listenerFns || [], fn);
|
2830
|
-
if (listenerFns && listenerFns.length > 0) {
|
2831
|
-
return;
|
2832
|
-
}
|
2833
2858
|
}
|
2859
|
+
if (!(isDefined(fn) && listenerFns && listenerFns.length > 0)) {
|
2860
|
+
removeEventListenerFn(element, type, handle);
|
2861
|
+
delete events[type];
|
2862
|
+
}
|
2863
|
+
};
|
2834
2864
|
|
2835
|
-
|
2836
|
-
|
2865
|
+
forEach(type.split(' '), function(type) {
|
2866
|
+
removeHandler(type);
|
2867
|
+
if (MOUSE_EVENT_MAP[type]) {
|
2868
|
+
removeHandler(MOUSE_EVENT_MAP[type]);
|
2869
|
+
}
|
2837
2870
|
});
|
2838
2871
|
}
|
2839
2872
|
}
|
@@ -3288,6 +3321,9 @@ function createEventHandler(element, events) {
|
|
3288
3321
|
return event.immediatePropagationStopped === true;
|
3289
3322
|
};
|
3290
3323
|
|
3324
|
+
// Some events have special handlers that wrap the real handler
|
3325
|
+
var handlerWrapper = eventFns.specialHandlerWrapper || defaultHandlerWrapper;
|
3326
|
+
|
3291
3327
|
// Copy event handlers in case event handlers array is modified during execution.
|
3292
3328
|
if ((eventFnsLength > 1)) {
|
3293
3329
|
eventFns = shallowCopy(eventFns);
|
@@ -3295,7 +3331,7 @@ function createEventHandler(element, events) {
|
|
3295
3331
|
|
3296
3332
|
for (var i = 0; i < eventFnsLength; i++) {
|
3297
3333
|
if (!event.isImmediatePropagationStopped()) {
|
3298
|
-
|
3334
|
+
handlerWrapper(element, event, eventFns[i]);
|
3299
3335
|
}
|
3300
3336
|
}
|
3301
3337
|
};
|
@@ -3306,6 +3342,22 @@ function createEventHandler(element, events) {
|
|
3306
3342
|
return eventHandler;
|
3307
3343
|
}
|
3308
3344
|
|
3345
|
+
function defaultHandlerWrapper(element, event, handler) {
|
3346
|
+
handler.call(element, event);
|
3347
|
+
}
|
3348
|
+
|
3349
|
+
function specialMouseHandlerWrapper(target, event, handler) {
|
3350
|
+
// Refer to jQuery's implementation of mouseenter & mouseleave
|
3351
|
+
// Read about mouseenter and mouseleave:
|
3352
|
+
// http://www.quirksmode.org/js/events_mouse.html#link8
|
3353
|
+
var related = event.relatedTarget;
|
3354
|
+
// For mousenter/leave call the handler if related is outside the target.
|
3355
|
+
// NB: No relatedTarget if the mouse left/entered the browser window
|
3356
|
+
if (!related || (related !== target && !jqLiteContains.call(target, related))) {
|
3357
|
+
handler.call(target, event);
|
3358
|
+
}
|
3359
|
+
}
|
3360
|
+
|
3309
3361
|
//////////////////////////////////////////
|
3310
3362
|
// Functions iterating traversal.
|
3311
3363
|
// These functions chain results into a single
|
@@ -3334,35 +3386,28 @@ forEach({
|
|
3334
3386
|
var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];
|
3335
3387
|
var i = types.length;
|
3336
3388
|
|
3337
|
-
|
3338
|
-
type = types[i];
|
3389
|
+
var addHandler = function(type, specialHandlerWrapper, noEventListener) {
|
3339
3390
|
var eventFns = events[type];
|
3340
3391
|
|
3341
3392
|
if (!eventFns) {
|
3342
|
-
events[type] = [];
|
3343
|
-
|
3344
|
-
if (type
|
3345
|
-
|
3346
|
-
// Read about mouseenter and mouseleave:
|
3347
|
-
// http://www.quirksmode.org/js/events_mouse.html#link8
|
3348
|
-
|
3349
|
-
jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) {
|
3350
|
-
var target = this, related = event.relatedTarget;
|
3351
|
-
// For mousenter/leave call the handler if related is outside the target.
|
3352
|
-
// NB: No relatedTarget if the mouse left/entered the browser window
|
3353
|
-
if (!related || (related !== target && !target.contains(related))) {
|
3354
|
-
handle(event, type);
|
3355
|
-
}
|
3356
|
-
});
|
3357
|
-
|
3358
|
-
} else {
|
3359
|
-
if (type !== '$destroy') {
|
3360
|
-
addEventListenerFn(element, type, handle);
|
3361
|
-
}
|
3393
|
+
eventFns = events[type] = [];
|
3394
|
+
eventFns.specialHandlerWrapper = specialHandlerWrapper;
|
3395
|
+
if (type !== '$destroy' && !noEventListener) {
|
3396
|
+
addEventListenerFn(element, type, handle);
|
3362
3397
|
}
|
3363
|
-
eventFns = events[type];
|
3364
3398
|
}
|
3399
|
+
|
3365
3400
|
eventFns.push(fn);
|
3401
|
+
};
|
3402
|
+
|
3403
|
+
while (i--) {
|
3404
|
+
type = types[i];
|
3405
|
+
if (MOUSE_EVENT_MAP[type]) {
|
3406
|
+
addHandler(MOUSE_EVENT_MAP[type], specialMouseHandlerWrapper);
|
3407
|
+
addHandler(type, undefined, true);
|
3408
|
+
} else {
|
3409
|
+
addHandler(type);
|
3410
|
+
}
|
3366
3411
|
}
|
3367
3412
|
},
|
3368
3413
|
|
@@ -4543,7 +4588,7 @@ function $AnchorScrollProvider() {
|
|
4543
4588
|
* When called, it scrolls to the element related to the specified `hash` or (if omitted) to the
|
4544
4589
|
* current value of {@link ng.$location#hash $location.hash()}, according to the rules specified
|
4545
4590
|
* in the
|
4546
|
-
* [HTML5 spec](http://
|
4591
|
+
* [HTML5 spec](http://www.w3.org/html/wg/drafts/html/master/browsers.html#the-indicated-part-of-the-document).
|
4547
4592
|
*
|
4548
4593
|
* It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to
|
4549
4594
|
* match any anchor whenever it changes. This can be disabled by calling
|
@@ -5058,7 +5103,7 @@ var $AnimateProvider = ['$provide', function($provide) {
|
|
5058
5103
|
* when an animation is detected (and animations are enabled), $animate will do the heavy lifting
|
5059
5104
|
* to ensure that animation runs with the triggered DOM operation.
|
5060
5105
|
*
|
5061
|
-
* By default $animate doesn't trigger
|
5106
|
+
* By default $animate doesn't trigger any animations. This is because the `ngAnimate` module isn't
|
5062
5107
|
* included and only when it is active then the animation hooks that `$animate` triggers will be
|
5063
5108
|
* functional. Once active then all structural `ng-` directives will trigger animations as they perform
|
5064
5109
|
* their DOM-related operations (enter, leave and move). Other directives such as `ngClass`,
|
@@ -5910,9 +5955,9 @@ function $CacheFactoryProvider() {
|
|
5910
5955
|
|
5911
5956
|
var size = 0,
|
5912
5957
|
stats = extend({}, options, {id: cacheId}),
|
5913
|
-
data =
|
5958
|
+
data = createMap(),
|
5914
5959
|
capacity = (options && options.capacity) || Number.MAX_VALUE,
|
5915
|
-
lruHash =
|
5960
|
+
lruHash = createMap(),
|
5916
5961
|
freshEnd = null,
|
5917
5962
|
staleEnd = null;
|
5918
5963
|
|
@@ -6040,6 +6085,8 @@ function $CacheFactoryProvider() {
|
|
6040
6085
|
delete lruHash[key];
|
6041
6086
|
}
|
6042
6087
|
|
6088
|
+
if (!(key in data)) return;
|
6089
|
+
|
6043
6090
|
delete data[key];
|
6044
6091
|
size--;
|
6045
6092
|
},
|
@@ -6054,9 +6101,9 @@ function $CacheFactoryProvider() {
|
|
6054
6101
|
* Clears the cache object of any entries.
|
6055
6102
|
*/
|
6056
6103
|
removeAll: function() {
|
6057
|
-
data =
|
6104
|
+
data = createMap();
|
6058
6105
|
size = 0;
|
6059
|
-
lruHash =
|
6106
|
+
lruHash = createMap();
|
6060
6107
|
freshEnd = staleEnd = null;
|
6061
6108
|
},
|
6062
6109
|
|
@@ -7457,6 +7504,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
7457
7504
|
return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
|
7458
7505
|
},
|
7459
7506
|
NG_ATTR_BINDING = /^ngAttr[A-Z]/;
|
7507
|
+
var MULTI_ELEMENT_DIR_RE = /^(.+)Start$/;
|
7460
7508
|
|
7461
7509
|
compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {
|
7462
7510
|
var bindings = $element.data('$binding') || [];
|
@@ -7509,6 +7557,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
7509
7557
|
return function publicLinkFn(scope, cloneConnectFn, options) {
|
7510
7558
|
assertArg(scope, 'scope');
|
7511
7559
|
|
7560
|
+
if (previousCompileContext && previousCompileContext.needsNewScope) {
|
7561
|
+
// A parent directive did a replace and a directive on this element asked
|
7562
|
+
// for transclusion, which caused us to lose a layer of element on which
|
7563
|
+
// we could hold the new transclusion scope, so we will create it manually
|
7564
|
+
// here.
|
7565
|
+
scope = scope.$parent.$new();
|
7566
|
+
}
|
7567
|
+
|
7512
7568
|
options = options || {};
|
7513
7569
|
var parentBoundTranscludeFn = options.parentBoundTranscludeFn,
|
7514
7570
|
transcludeControllers = options.transcludeControllers,
|
@@ -7654,11 +7710,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
7654
7710
|
if (nodeLinkFn.scope) {
|
7655
7711
|
childScope = scope.$new();
|
7656
7712
|
compile.$$addScopeInfo(jqLite(node), childScope);
|
7657
|
-
var destroyBindings = nodeLinkFn.$$destroyBindings;
|
7658
|
-
if (destroyBindings) {
|
7659
|
-
nodeLinkFn.$$destroyBindings = null;
|
7660
|
-
childScope.$on('$destroyed', destroyBindings);
|
7661
|
-
}
|
7662
7713
|
} else {
|
7663
7714
|
childScope = scope;
|
7664
7715
|
}
|
@@ -7677,8 +7728,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
7677
7728
|
childBoundTranscludeFn = null;
|
7678
7729
|
}
|
7679
7730
|
|
7680
|
-
nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn
|
7681
|
-
nodeLinkFn);
|
7731
|
+
nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
|
7682
7732
|
|
7683
7733
|
} else if (childLinkFn) {
|
7684
7734
|
childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);
|
@@ -7747,13 +7797,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
7747
7797
|
});
|
7748
7798
|
}
|
7749
7799
|
|
7750
|
-
var
|
7751
|
-
if (directiveIsMultiElement(
|
7752
|
-
|
7753
|
-
|
7754
|
-
|
7755
|
-
name = name.substr(0, name.length - 6);
|
7756
|
-
}
|
7800
|
+
var multiElementMatch = ngAttrName.match(MULTI_ELEMENT_DIR_RE);
|
7801
|
+
if (multiElementMatch && directiveIsMultiElement(multiElementMatch[1])) {
|
7802
|
+
attrStartName = name;
|
7803
|
+
attrEndName = name.substr(0, name.length - 5) + 'end';
|
7804
|
+
name = name.substr(0, name.length - 6);
|
7757
7805
|
}
|
7758
7806
|
|
7759
7807
|
nName = directiveNormalize(name.toLowerCase());
|
@@ -7992,7 +8040,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
7992
8040
|
} else {
|
7993
8041
|
$template = jqLite(jqLiteClone(compileNode)).contents();
|
7994
8042
|
$compileNode.empty(); // clear contents
|
7995
|
-
childTranscludeFn = compile($template, transcludeFn
|
8043
|
+
childTranscludeFn = compile($template, transcludeFn, undefined,
|
8044
|
+
undefined, { needsNewScope: directive.$$isolateScope || directive.$$newScope});
|
7996
8045
|
}
|
7997
8046
|
}
|
7998
8047
|
|
@@ -8034,8 +8083,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
8034
8083
|
var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);
|
8035
8084
|
var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));
|
8036
8085
|
|
8037
|
-
if (newIsolateScopeDirective) {
|
8038
|
-
|
8086
|
+
if (newIsolateScopeDirective || newScopeDirective) {
|
8087
|
+
// The original directive caused the current element to be replaced but this element
|
8088
|
+
// also needs to have a new scope, so we need to tell the template directives
|
8089
|
+
// that they would need to get their scope from further up, if they require transclusion
|
8090
|
+
markDirectiveScope(templateDirectives, newIsolateScopeDirective, newScopeDirective);
|
8039
8091
|
}
|
8040
8092
|
directives = directives.concat(templateDirectives).concat(unprocessedDirectives);
|
8041
8093
|
mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
|
@@ -8188,10 +8240,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
8188
8240
|
return elementControllers;
|
8189
8241
|
}
|
8190
8242
|
|
8191
|
-
function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn
|
8192
|
-
|
8193
|
-
|
8194
|
-
attrs;
|
8243
|
+
function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
|
8244
|
+
var linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element,
|
8245
|
+
attrs, removeScopeBindingWatches, removeControllerBindingWatches;
|
8195
8246
|
|
8196
8247
|
if (compileNode === linkNode) {
|
8197
8248
|
attrs = templateAttrs;
|
@@ -8201,8 +8252,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
8201
8252
|
attrs = new Attributes($element, templateAttrs);
|
8202
8253
|
}
|
8203
8254
|
|
8255
|
+
controllerScope = scope;
|
8204
8256
|
if (newIsolateScopeDirective) {
|
8205
8257
|
isolateScope = scope.$new(true);
|
8258
|
+
} else if (newScopeDirective) {
|
8259
|
+
controllerScope = scope.$parent;
|
8206
8260
|
}
|
8207
8261
|
|
8208
8262
|
if (boundTranscludeFn) {
|
@@ -8223,42 +8277,34 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
8223
8277
|
compile.$$addScopeClass($element, true);
|
8224
8278
|
isolateScope.$$isolateBindings =
|
8225
8279
|
newIsolateScopeDirective.$$isolateBindings;
|
8226
|
-
initializeDirectiveBindings(scope, attrs, isolateScope,
|
8227
|
-
|
8228
|
-
|
8280
|
+
removeScopeBindingWatches = initializeDirectiveBindings(scope, attrs, isolateScope,
|
8281
|
+
isolateScope.$$isolateBindings,
|
8282
|
+
newIsolateScopeDirective);
|
8283
|
+
if (removeScopeBindingWatches) {
|
8284
|
+
isolateScope.$on('$destroy', removeScopeBindingWatches);
|
8285
|
+
}
|
8229
8286
|
}
|
8230
|
-
|
8231
|
-
|
8232
|
-
|
8233
|
-
var
|
8234
|
-
var
|
8235
|
-
|
8236
|
-
|
8237
|
-
|
8238
|
-
|
8239
|
-
|
8240
|
-
controllerForBindings = controller;
|
8241
|
-
thisLinkFn.$$destroyBindings =
|
8242
|
-
initializeDirectiveBindings(scope, attrs, controller.instance,
|
8243
|
-
bindings, scopeDirective);
|
8244
|
-
}
|
8287
|
+
|
8288
|
+
// Initialize bindToController bindings
|
8289
|
+
for (var name in elementControllers) {
|
8290
|
+
var controllerDirective = controllerDirectives[name];
|
8291
|
+
var controller = elementControllers[name];
|
8292
|
+
var bindings = controllerDirective.$$bindings.bindToController;
|
8293
|
+
|
8294
|
+
if (controller.identifier && bindings) {
|
8295
|
+
removeControllerBindingWatches =
|
8296
|
+
initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
|
8245
8297
|
}
|
8246
|
-
|
8247
|
-
|
8248
|
-
|
8249
|
-
|
8250
|
-
|
8251
|
-
|
8252
|
-
|
8253
|
-
|
8254
|
-
|
8255
|
-
|
8256
|
-
// Remove and re-install bindToController bindings
|
8257
|
-
thisLinkFn.$$destroyBindings();
|
8258
|
-
thisLinkFn.$$destroyBindings =
|
8259
|
-
initializeDirectiveBindings(scope, attrs, controllerResult, bindings, scopeDirective);
|
8260
|
-
}
|
8261
|
-
}
|
8298
|
+
|
8299
|
+
var controllerResult = controller();
|
8300
|
+
if (controllerResult !== controller.instance) {
|
8301
|
+
// If the controller constructor has a return value, overwrite the instance
|
8302
|
+
// from setupControllers
|
8303
|
+
controller.instance = controllerResult;
|
8304
|
+
$element.data('$' + controllerDirective.name + 'Controller', controllerResult);
|
8305
|
+
removeControllerBindingWatches && removeControllerBindingWatches();
|
8306
|
+
removeControllerBindingWatches =
|
8307
|
+
initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
|
8262
8308
|
}
|
8263
8309
|
}
|
8264
8310
|
|
@@ -8318,10 +8364,15 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
8318
8364
|
}
|
8319
8365
|
}
|
8320
8366
|
|
8321
|
-
|
8322
|
-
|
8367
|
+
// Depending upon the context in which a directive finds itself it might need to have a new isolated
|
8368
|
+
// or child scope created. For instance:
|
8369
|
+
// * if the directive has been pulled into a template because another directive with a higher priority
|
8370
|
+
// asked for element transclusion
|
8371
|
+
// * if the directive itself asks for transclusion but it is at the root of a template and the original
|
8372
|
+
// element was replaced. See https://github.com/angular/angular.js/issues/12936
|
8373
|
+
function markDirectiveScope(directives, isolateScope, newScope) {
|
8323
8374
|
for (var j = 0, jj = directives.length; j < jj; j++) {
|
8324
|
-
directives[j] = inherit(directives[j], {$$isolateScope:
|
8375
|
+
directives[j] = inherit(directives[j], {$$isolateScope: isolateScope, $$newScope: newScope});
|
8325
8376
|
}
|
8326
8377
|
}
|
8327
8378
|
|
@@ -8468,7 +8519,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
8468
8519
|
var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);
|
8469
8520
|
|
8470
8521
|
if (isObject(origAsyncDirective.scope)) {
|
8471
|
-
|
8522
|
+
// the original directive that caused the template to be loaded async required
|
8523
|
+
// an isolate scope
|
8524
|
+
markDirectiveScope(templateDirectives, true);
|
8472
8525
|
}
|
8473
8526
|
directives = templateDirectives.concat(directives);
|
8474
8527
|
mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
|
@@ -8517,7 +8570,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
8517
8570
|
childBoundTranscludeFn = boundTranscludeFn;
|
8518
8571
|
}
|
8519
8572
|
afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
|
8520
|
-
childBoundTranscludeFn
|
8573
|
+
childBoundTranscludeFn);
|
8521
8574
|
}
|
8522
8575
|
linkQueue = null;
|
8523
8576
|
});
|
@@ -8534,8 +8587,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
8534
8587
|
if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
|
8535
8588
|
childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
|
8536
8589
|
}
|
8537
|
-
afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn
|
8538
|
-
afterTemplateNodeLinkFn);
|
8590
|
+
afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);
|
8539
8591
|
}
|
8540
8592
|
};
|
8541
8593
|
}
|
@@ -8747,7 +8799,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
8747
8799
|
// Copy over user data (that includes Angular's $scope etc.). Don't copy private
|
8748
8800
|
// data here because there's no public interface in jQuery to do that and copying over
|
8749
8801
|
// event listeners (which is the main use of private data) wouldn't work anyway.
|
8750
|
-
jqLite
|
8802
|
+
jqLite.data(newNode, jqLite.data(firstElementToRemove));
|
8751
8803
|
|
8752
8804
|
// Remove data of the replaced element. We cannot just call .remove()
|
8753
8805
|
// on the element it since that would deallocate scope that is needed
|
@@ -8795,9 +8847,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
8795
8847
|
|
8796
8848
|
// Set up $watches for isolate scope and controller bindings. This process
|
8797
8849
|
// only occurs for isolate scopes and new scopes with controllerAs.
|
8798
|
-
function initializeDirectiveBindings(scope, attrs, destination, bindings,
|
8799
|
-
|
8800
|
-
var onNewScopeDestroyed;
|
8850
|
+
function initializeDirectiveBindings(scope, attrs, destination, bindings, directive) {
|
8851
|
+
var removeWatchCollection = [];
|
8801
8852
|
forEach(bindings, function(definition, scopeName) {
|
8802
8853
|
var attrName = definition.attrName,
|
8803
8854
|
optional = definition.optional,
|
@@ -8859,14 +8910,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
8859
8910
|
return lastValue = parentValue;
|
8860
8911
|
};
|
8861
8912
|
parentValueWatch.$stateful = true;
|
8862
|
-
var
|
8913
|
+
var removeWatch;
|
8863
8914
|
if (definition.collection) {
|
8864
|
-
|
8915
|
+
removeWatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
|
8865
8916
|
} else {
|
8866
|
-
|
8917
|
+
removeWatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
|
8867
8918
|
}
|
8868
|
-
|
8869
|
-
onNewScopeDestroyed.push(unwatch);
|
8919
|
+
removeWatchCollection.push(removeWatch);
|
8870
8920
|
break;
|
8871
8921
|
|
8872
8922
|
case '&':
|
@@ -8882,16 +8932,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|
8882
8932
|
break;
|
8883
8933
|
}
|
8884
8934
|
});
|
8885
|
-
|
8886
|
-
|
8887
|
-
|
8935
|
+
|
8936
|
+
return removeWatchCollection.length && function removeWatches() {
|
8937
|
+
for (var i = 0, ii = removeWatchCollection.length; i < ii; ++i) {
|
8938
|
+
removeWatchCollection[i]();
|
8888
8939
|
}
|
8889
|
-
}
|
8890
|
-
if (newScope && destroyBindings !== noop) {
|
8891
|
-
newScope.$on('$destroy', destroyBindings);
|
8892
|
-
return noop;
|
8893
|
-
}
|
8894
|
-
return destroyBindings;
|
8940
|
+
};
|
8895
8941
|
}
|
8896
8942
|
}];
|
8897
8943
|
}
|
@@ -9616,9 +9662,9 @@ function $HttpProvider() {
|
|
9616
9662
|
* Configure `$http` service to return promises without the shorthand methods `success` and `error`.
|
9617
9663
|
* This should be used to make sure that applications work without these methods.
|
9618
9664
|
*
|
9619
|
-
* Defaults to
|
9665
|
+
* Defaults to true. If no value is specified, returns the current configured value.
|
9620
9666
|
*
|
9621
|
-
* @param {boolean=} value If true, `$http` will return a
|
9667
|
+
* @param {boolean=} value If true, `$http` will return a promise with the deprecated legacy `success` and `error` methods.
|
9622
9668
|
*
|
9623
9669
|
* @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.
|
9624
9670
|
* otherwise, returns the current configured value.
|
@@ -10270,11 +10316,8 @@ function $HttpProvider() {
|
|
10270
10316
|
function transformResponse(response) {
|
10271
10317
|
// make a copy since the response must be cacheable
|
10272
10318
|
var resp = extend({}, response);
|
10273
|
-
|
10274
|
-
|
10275
|
-
} else {
|
10276
|
-
resp.data = transformData(response.data, response.headers, response.status, config.transformResponse);
|
10277
|
-
}
|
10319
|
+
resp.data = transformData(response.data, response.headers, response.status,
|
10320
|
+
config.transformResponse);
|
10278
10321
|
return (isSuccess(response.status))
|
10279
10322
|
? resp
|
10280
10323
|
: $q.reject(resp);
|
@@ -11908,9 +11951,9 @@ var locationPrototype = {
|
|
11908
11951
|
* @description
|
11909
11952
|
* This method is getter / setter.
|
11910
11953
|
*
|
11911
|
-
*
|
11954
|
+
* Returns the hash fragment when called without any parameters.
|
11912
11955
|
*
|
11913
|
-
*
|
11956
|
+
* Changes the hash fragment when called with a parameter and returns `$location`.
|
11914
11957
|
*
|
11915
11958
|
*
|
11916
11959
|
* ```js
|
@@ -11931,8 +11974,8 @@ var locationPrototype = {
|
|
11931
11974
|
* @name $location#replace
|
11932
11975
|
*
|
11933
11976
|
* @description
|
11934
|
-
* If called, all changes to $location during current `$digest` will
|
11935
|
-
* record, instead of adding new one.
|
11977
|
+
* If called, all changes to $location during the current `$digest` will replace the current history
|
11978
|
+
* record, instead of adding a new one.
|
11936
11979
|
*/
|
11937
11980
|
replace: function() {
|
11938
11981
|
this.$$replace = true;
|
@@ -12252,7 +12295,7 @@ function $LocationProvider() {
|
|
12252
12295
|
var oldUrl = $location.absUrl();
|
12253
12296
|
var oldState = $location.$$state;
|
12254
12297
|
var defaultPrevented;
|
12255
|
-
|
12298
|
+
newUrl = trimEmptyHash(newUrl);
|
12256
12299
|
$location.$$parse(newUrl);
|
12257
12300
|
$location.$$state = newState;
|
12258
12301
|
|
@@ -14393,13 +14436,14 @@ function $ParseProvider() {
|
|
14393
14436
|
function addInterceptor(parsedExpression, interceptorFn) {
|
14394
14437
|
if (!interceptorFn) return parsedExpression;
|
14395
14438
|
var watchDelegate = parsedExpression.$$watchDelegate;
|
14439
|
+
var useInputs = false;
|
14396
14440
|
|
14397
14441
|
var regularWatch =
|
14398
14442
|
watchDelegate !== oneTimeLiteralWatchDelegate &&
|
14399
14443
|
watchDelegate !== oneTimeWatchDelegate;
|
14400
14444
|
|
14401
14445
|
var fn = regularWatch ? function regularInterceptedExpression(scope, locals, assign, inputs) {
|
14402
|
-
var value = parsedExpression(scope, locals, assign, inputs);
|
14446
|
+
var value = useInputs && inputs ? inputs[0] : parsedExpression(scope, locals, assign, inputs);
|
14403
14447
|
return interceptorFn(value, scope, locals);
|
14404
14448
|
} : function oneTimeInterceptedExpression(scope, locals, assign, inputs) {
|
14405
14449
|
var value = parsedExpression(scope, locals, assign, inputs);
|
@@ -14417,6 +14461,7 @@ function $ParseProvider() {
|
|
14417
14461
|
// If there is an interceptor, but no watchDelegate then treat the interceptor like
|
14418
14462
|
// we treat filters - it is assumed to be a pure function unless flagged with $stateful
|
14419
14463
|
fn.$$watchDelegate = inputsWatchDelegate;
|
14464
|
+
useInputs = !parsedExpression.inputs;
|
14420
14465
|
fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression];
|
14421
14466
|
}
|
14422
14467
|
|
@@ -14478,6 +14523,8 @@ function $ParseProvider() {
|
|
14478
14523
|
*
|
14479
14524
|
* Note: progress/notify callbacks are not currently supported via the ES6-style interface.
|
14480
14525
|
*
|
14526
|
+
* Note: unlike ES6 behaviour, an exception thrown in the constructor function will NOT implicitly reject the promise.
|
14527
|
+
*
|
14481
14528
|
* However, the more traditional CommonJS-style usage is still available, and documented below.
|
14482
14529
|
*
|
14483
14530
|
* [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an
|
@@ -15062,15 +15109,15 @@ function $$RAFProvider() { //rAF
|
|
15062
15109
|
* exposed as $$____ properties
|
15063
15110
|
*
|
15064
15111
|
* Loop operations are optimized by using while(count--) { ... }
|
15065
|
-
* -
|
15112
|
+
* - This means that in order to keep the same order of execution as addition we have to add
|
15066
15113
|
* items to the array at the beginning (unshift) instead of at the end (push)
|
15067
15114
|
*
|
15068
15115
|
* Child scopes are created and removed often
|
15069
|
-
* - Using an array would be slow since inserts in middle are expensive so we use linked
|
15116
|
+
* - Using an array would be slow since inserts in the middle are expensive; so we use linked lists
|
15070
15117
|
*
|
15071
|
-
* There are
|
15072
|
-
*
|
15073
|
-
*
|
15118
|
+
* There are fewer watches than observers. This is why you don't want the observer to be implemented
|
15119
|
+
* in the same way as watch. Watch requires return of the initialization function which is expensive
|
15120
|
+
* to construct.
|
15074
15121
|
*/
|
15075
15122
|
|
15076
15123
|
|
@@ -15112,7 +15159,7 @@ function $$RAFProvider() { //rAF
|
|
15112
15159
|
* Every application has a single root {@link ng.$rootScope.Scope scope}.
|
15113
15160
|
* All other scopes are descendant scopes of the root scope. Scopes provide separation
|
15114
15161
|
* between the model and the view, via a mechanism for watching the model for changes.
|
15115
|
-
* They also provide
|
15162
|
+
* They also provide event emission/broadcast and subscription facility. See the
|
15116
15163
|
* {@link guide/scope developer guide on scopes}.
|
15117
15164
|
*/
|
15118
15165
|
function $RootScopeProvider() {
|
@@ -15149,6 +15196,29 @@ function $RootScopeProvider() {
|
|
15149
15196
|
$event.currentScope.$$destroyed = true;
|
15150
15197
|
}
|
15151
15198
|
|
15199
|
+
function cleanUpScope($scope) {
|
15200
|
+
|
15201
|
+
if (msie === 9) {
|
15202
|
+
// There is a memory leak in IE9 if all child scopes are not disconnected
|
15203
|
+
// completely when a scope is destroyed. So this code will recurse up through
|
15204
|
+
// all this scopes children
|
15205
|
+
//
|
15206
|
+
// See issue https://github.com/angular/angular.js/issues/10706
|
15207
|
+
$scope.$$childHead && cleanUpScope($scope.$$childHead);
|
15208
|
+
$scope.$$nextSibling && cleanUpScope($scope.$$nextSibling);
|
15209
|
+
}
|
15210
|
+
|
15211
|
+
// The code below works around IE9 and V8's memory leaks
|
15212
|
+
//
|
15213
|
+
// See:
|
15214
|
+
// - https://code.google.com/p/v8/issues/detail?id=2073#c26
|
15215
|
+
// - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909
|
15216
|
+
// - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
|
15217
|
+
|
15218
|
+
$scope.$parent = $scope.$$nextSibling = $scope.$$prevSibling = $scope.$$childHead =
|
15219
|
+
$scope.$$childTail = $scope.$root = $scope.$$watchers = null;
|
15220
|
+
}
|
15221
|
+
|
15152
15222
|
/**
|
15153
15223
|
* @ngdoc type
|
15154
15224
|
* @name $rootScope.Scope
|
@@ -15945,16 +16015,9 @@ function $RootScopeProvider() {
|
|
15945
16015
|
this.$on = this.$watch = this.$watchGroup = function() { return noop; };
|
15946
16016
|
this.$$listeners = {};
|
15947
16017
|
|
15948
|
-
//
|
15949
|
-
|
15950
|
-
|
15951
|
-
// see:
|
15952
|
-
// - https://code.google.com/p/v8/issues/detail?id=2073#c26
|
15953
|
-
// - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909
|
15954
|
-
// - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
|
15955
|
-
|
15956
|
-
this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =
|
15957
|
-
this.$$childTail = this.$root = this.$$watchers = null;
|
16018
|
+
// Disconnect the next sibling to prevent `cleanUpScope` destroying those too
|
16019
|
+
this.$$nextSibling = null;
|
16020
|
+
cleanUpScope(this);
|
15958
16021
|
},
|
15959
16022
|
|
15960
16023
|
/**
|
@@ -16950,7 +17013,7 @@ function $SceDelegateProvider() {
|
|
16950
17013
|
* By default, Angular only loads templates from the same domain and protocol as the application
|
16951
17014
|
* document. This is done by calling {@link ng.$sce#getTrustedResourceUrl
|
16952
17015
|
* $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or
|
16953
|
-
* protocols, you may either
|
17016
|
+
* protocols, you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist
|
16954
17017
|
* them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.
|
16955
17018
|
*
|
16956
17019
|
* *Please note*:
|
@@ -19201,7 +19264,7 @@ function limitToFilter() {
|
|
19201
19264
|
if (!isArray(input) && !isString(input)) return input;
|
19202
19265
|
|
19203
19266
|
begin = (!begin || isNaN(begin)) ? 0 : toInt(begin);
|
19204
|
-
begin = (begin < 0
|
19267
|
+
begin = (begin < 0) ? Math.max(0, input.length + begin) : begin;
|
19205
19268
|
|
19206
19269
|
if (limit >= 0) {
|
19207
19270
|
return input.slice(begin, begin + limit);
|
@@ -20561,7 +20624,8 @@ var ngFormDirective = formDirectiveFactory(true);
|
|
20561
20624
|
|
20562
20625
|
// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231
|
20563
20626
|
var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/;
|
20564
|
-
|
20627
|
+
// See valid URLs in RFC3987 (http://tools.ietf.org/html/rfc3987)
|
20628
|
+
var URL_REGEXP = /^[A-Za-z][A-Za-z\d.+-]*:\/*(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?(?:\/[\w#!:.?+=&%@\-/]*)?$/;
|
20565
20629
|
var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
|
20566
20630
|
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/;
|
20567
20631
|
var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
|
@@ -24127,7 +24191,13 @@ var ngIfDirective = ['$animate', function($animate) {
|
|
24127
24191
|
* @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,
|
24128
24192
|
* make sure you wrap it in **single** quotes, e.g. `src="'myPartialTemplate.html'"`.
|
24129
24193
|
* @param {string=} onload Expression to evaluate when a new partial is loaded.
|
24130
|
-
*
|
24194
|
+
* <div class="alert alert-warning">
|
24195
|
+
* **Note:** When using onload on SVG elements in IE11, the browser will try to call
|
24196
|
+
* a function with the name on the window element, which will usually throw a
|
24197
|
+
* "function is undefined" error. To fix this, you can instead use `data-onload` or a
|
24198
|
+
* different form that {@link guide/directive#normalization matches} `onload`.
|
24199
|
+
* </div>
|
24200
|
+
*
|
24131
24201
|
* @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll
|
24132
24202
|
* $anchorScroll} to scroll the viewport after the content is loaded.
|
24133
24203
|
*
|
@@ -25720,12 +25790,13 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
|
|
25720
25790
|
</label><br />
|
25721
25791
|
</form>
|
25722
25792
|
<pre>user.name = <span ng-bind="user.name"></span></pre>
|
25793
|
+
<pre>user.data = <span ng-bind="user.data"></span></pre>
|
25723
25794
|
</div>
|
25724
25795
|
</file>
|
25725
25796
|
<file name="app.js">
|
25726
25797
|
angular.module('optionsExample', [])
|
25727
25798
|
.controller('ExampleController', ['$scope', function($scope) {
|
25728
|
-
$scope.user = { name: '
|
25799
|
+
$scope.user = { name: 'John', data: '' };
|
25729
25800
|
|
25730
25801
|
$scope.cancel = function(e) {
|
25731
25802
|
if (e.keyCode == 27) {
|
@@ -25740,20 +25811,20 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
|
|
25740
25811
|
var other = element(by.model('user.data'));
|
25741
25812
|
|
25742
25813
|
it('should allow custom events', function() {
|
25743
|
-
input.sendKeys('
|
25814
|
+
input.sendKeys(' Doe');
|
25744
25815
|
input.click();
|
25745
|
-
expect(model.getText()).toEqual('
|
25816
|
+
expect(model.getText()).toEqual('John');
|
25746
25817
|
other.click();
|
25747
|
-
expect(model.getText()).toEqual('
|
25818
|
+
expect(model.getText()).toEqual('John Doe');
|
25748
25819
|
});
|
25749
25820
|
|
25750
25821
|
it('should $rollbackViewValue when model changes', function() {
|
25751
|
-
input.sendKeys('
|
25752
|
-
expect(input.getAttribute('value')).toEqual('
|
25822
|
+
input.sendKeys(' Doe');
|
25823
|
+
expect(input.getAttribute('value')).toEqual('John Doe');
|
25753
25824
|
input.sendKeys(protractor.Key.ESCAPE);
|
25754
|
-
expect(input.getAttribute('value')).toEqual('
|
25825
|
+
expect(input.getAttribute('value')).toEqual('John');
|
25755
25826
|
other.click();
|
25756
|
-
expect(model.getText()).toEqual('
|
25827
|
+
expect(model.getText()).toEqual('John');
|
25757
25828
|
});
|
25758
25829
|
</file>
|
25759
25830
|
</example>
|
@@ -25779,7 +25850,7 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
|
|
25779
25850
|
<file name="app.js">
|
25780
25851
|
angular.module('optionsExample', [])
|
25781
25852
|
.controller('ExampleController', ['$scope', function($scope) {
|
25782
|
-
$scope.user = { name: '
|
25853
|
+
$scope.user = { name: 'Igor' };
|
25783
25854
|
}]);
|
25784
25855
|
</file>
|
25785
25856
|
</example>
|
@@ -26012,19 +26083,27 @@ var ngOptionsMinErr = minErr('ngOptions');
|
|
26012
26083
|
*
|
26013
26084
|
* ## Complex Models (objects or collections)
|
26014
26085
|
*
|
26015
|
-
*
|
26016
|
-
* binding
|
26086
|
+
* By default, `ngModel` watches the model by reference, not value. This is important to know when
|
26087
|
+
* binding the select to a model that is an object or a collection.
|
26017
26088
|
*
|
26018
|
-
*
|
26019
|
-
*
|
26020
|
-
* the
|
26021
|
-
*
|
26022
|
-
* changes.
|
26089
|
+
* One issue occurs if you want to preselect an option. For example, if you set
|
26090
|
+
* the model to an object that is equal to an object in your collection, `ngOptions` won't be able to set the selection,
|
26091
|
+
* because the objects are not identical. So by default, you should always reference the item in your collection
|
26092
|
+
* for preselections, e.g.: `$scope.selected = $scope.collection[3]`.
|
26023
26093
|
*
|
26024
|
-
*
|
26025
|
-
*
|
26026
|
-
*
|
26094
|
+
* Another solution is to use a `track by` clause, because then `ngOptions` will track the identity
|
26095
|
+
* of the item not by reference, but by the result of the `track by` expression. For example, if your
|
26096
|
+
* collection items have an id property, you would `track by item.id`.
|
26097
|
+
*
|
26098
|
+
* A different issue with objects or collections is that ngModel won't detect if an object property or
|
26099
|
+
* a collection item changes. For that reason, `ngOptions` additionally watches the model using
|
26100
|
+
* `$watchCollection`, when the expression contains a `track by` clause or the the select has the `multiple` attribute.
|
26101
|
+
* This allows ngOptions to trigger a re-rendering of the options even if the actual object/collection
|
26102
|
+
* has not changed identity, but only a property on the object or an item in the collection changes.
|
26027
26103
|
*
|
26104
|
+
* Note that `$watchCollection` does a shallow comparison of the properties of the object (or the items in the collection
|
26105
|
+
* if the model is an array). This means that changing a property deeper than the first level inside the
|
26106
|
+
* object/collection will not trigger a re-rendering.
|
26028
26107
|
*
|
26029
26108
|
* ## `select` **`as`**
|
26030
26109
|
*
|
@@ -26037,17 +26116,13 @@ var ngOptionsMinErr = minErr('ngOptions');
|
|
26037
26116
|
* ### `select` **`as`** and **`track by`**
|
26038
26117
|
*
|
26039
26118
|
* <div class="alert alert-warning">
|
26040
|
-
*
|
26119
|
+
* Be careful when using `select` **`as`** and **`track by`** in the same expression.
|
26041
26120
|
* </div>
|
26042
26121
|
*
|
26043
|
-
*
|
26044
|
-
*
|
26045
|
-
* ```html
|
26046
|
-
* <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected"></select>
|
26047
|
-
* ```
|
26122
|
+
* Given this array of items on the $scope:
|
26048
26123
|
*
|
26049
26124
|
* ```js
|
26050
|
-
* $scope.
|
26125
|
+
* $scope.items = [{
|
26051
26126
|
* id: 1,
|
26052
26127
|
* label: 'aLabel',
|
26053
26128
|
* subItem: { name: 'aSubItem' }
|
@@ -26056,20 +26131,33 @@ var ngOptionsMinErr = minErr('ngOptions');
|
|
26056
26131
|
* label: 'bLabel',
|
26057
26132
|
* subItem: { name: 'bSubItem' }
|
26058
26133
|
* }];
|
26134
|
+
* ```
|
26135
|
+
*
|
26136
|
+
* This will work:
|
26059
26137
|
*
|
26060
|
-
*
|
26138
|
+
* ```html
|
26139
|
+
* <select ng-options="item as item.label for item in items track by item.id" ng-model="selected"></select>
|
26140
|
+
* ```
|
26141
|
+
* ```js
|
26142
|
+
* $scope.selected = $scope.items[0];
|
26061
26143
|
* ```
|
26062
26144
|
*
|
26063
|
-
*
|
26064
|
-
* of the data source (to `item` in this example). To calculate whether an element is selected, we do the
|
26065
|
-
* following:
|
26145
|
+
* but this will not work:
|
26066
26146
|
*
|
26067
|
-
*
|
26068
|
-
*
|
26069
|
-
*
|
26070
|
-
*
|
26071
|
-
*
|
26072
|
-
*
|
26147
|
+
* ```html
|
26148
|
+
* <select ng-options="item.subItem as item.label for item in items track by item.id" ng-model="selected"></select>
|
26149
|
+
* ```
|
26150
|
+
* ```js
|
26151
|
+
* $scope.selected = $scope.items[0].subItem;
|
26152
|
+
* ```
|
26153
|
+
*
|
26154
|
+
* In both examples, the **`track by`** expression is applied successfully to each `item` in the
|
26155
|
+
* `items` array. Because the selected option has been set programmatically in the controller, the
|
26156
|
+
* **`track by`** expression is also applied to the `ngModel` value. In the first example, the
|
26157
|
+
* `ngModel` value is `items[0]` and the **`track by`** expression evaluates to `items[0].id` with
|
26158
|
+
* no issue. In the second example, the `ngModel` value is `items[0].subItem` and the **`track by`**
|
26159
|
+
* expression evaluates to `items[0].subItem.id` (which is undefined). As a result, the model value
|
26160
|
+
* is not matched against any `<option>` and the `<select>` appears as having no selected value.
|
26073
26161
|
*
|
26074
26162
|
*
|
26075
26163
|
* @param {string} ngModel Assignable angular expression to data-bind to.
|
@@ -26371,11 +26459,8 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
26371
26459
|
var optionTemplate = document.createElement('option'),
|
26372
26460
|
optGroupTemplate = document.createElement('optgroup');
|
26373
26461
|
|
26374
|
-
|
26375
|
-
|
26376
|
-
terminal: true,
|
26377
|
-
require: ['select', '?ngModel'],
|
26378
|
-
link: function(scope, selectElement, attr, ctrls) {
|
26462
|
+
|
26463
|
+
function ngOptionsPostLink(scope, selectElement, attr, ctrls) {
|
26379
26464
|
|
26380
26465
|
// if ngModel is not defined, we don't need to do anything
|
26381
26466
|
var ngModelCtrl = ctrls[1];
|
@@ -26430,7 +26515,6 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
26430
26515
|
unknownOption.remove();
|
26431
26516
|
};
|
26432
26517
|
|
26433
|
-
|
26434
26518
|
// Update the controller methods for multiple selectable options
|
26435
26519
|
if (!multiple) {
|
26436
26520
|
|
@@ -26605,13 +26689,15 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
26605
26689
|
var emptyOption_ = emptyOption && emptyOption[0];
|
26606
26690
|
var unknownOption_ = unknownOption && unknownOption[0];
|
26607
26691
|
|
26692
|
+
// We cannot rely on the extracted empty option being the same as the compiled empty option,
|
26693
|
+
// because the compiled empty option might have been replaced by a comment because
|
26694
|
+
// it had an "element" transclusion directive on it (such as ngIf)
|
26608
26695
|
if (emptyOption_ || unknownOption_) {
|
26609
26696
|
while (current &&
|
26610
26697
|
(current === emptyOption_ ||
|
26611
26698
|
current === unknownOption_ ||
|
26612
|
-
|
26613
|
-
|
26614
|
-
// and insert comments (e.g. ngIf)
|
26699
|
+
current.nodeType === NODE_TYPE_COMMENT ||
|
26700
|
+
current.value === '')) {
|
26615
26701
|
current = current.nextSibling;
|
26616
26702
|
}
|
26617
26703
|
}
|
@@ -26708,7 +26794,20 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
26708
26794
|
}
|
26709
26795
|
|
26710
26796
|
}
|
26797
|
+
}
|
26711
26798
|
|
26799
|
+
return {
|
26800
|
+
restrict: 'A',
|
26801
|
+
terminal: true,
|
26802
|
+
require: ['select', '?ngModel'],
|
26803
|
+
link: {
|
26804
|
+
pre: function ngOptionsPreLink(scope, selectElement, attr, ctrls) {
|
26805
|
+
// Deactivate the SelectController.register method to prevent
|
26806
|
+
// option directives from accidentally registering themselves
|
26807
|
+
// (and unwanted $destroy handlers etc.)
|
26808
|
+
ctrls[0].registerOption = noop;
|
26809
|
+
},
|
26810
|
+
post: ngOptionsPostLink
|
26712
26811
|
}
|
26713
26812
|
};
|
26714
26813
|
}];
|
@@ -26995,7 +27094,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
|
|
26995
27094
|
* Version 1.4 removed the alphabetic sorting. We now rely on the order returned by the browser
|
26996
27095
|
* when running `for key in myObj`. It seems that browsers generally follow the strategy of providing
|
26997
27096
|
* keys in the order in which they were defined, although there are exceptions when keys are deleted
|
26998
|
-
* and reinstated. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-
|
27097
|
+
* and reinstated. See the [MDN page on `delete` for more info](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_notes).
|
26999
27098
|
*
|
27000
27099
|
* If this is not desired, the recommended workaround is to convert your object into an array
|
27001
27100
|
* that is sorted into the order that you prefer before providing it to `ngRepeat`. You could
|
@@ -27005,15 +27104,21 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
|
|
27005
27104
|
*
|
27006
27105
|
* # Tracking and Duplicates
|
27007
27106
|
*
|
27008
|
-
*
|
27107
|
+
* `ngRepeat` uses {@link $rootScope.Scope#$watchCollection $watchCollection} to detect changes in
|
27108
|
+
* the collection. When a change happens, ngRepeat then makes the corresponding changes to the DOM:
|
27009
27109
|
*
|
27010
27110
|
* * When an item is added, a new instance of the template is added to the DOM.
|
27011
27111
|
* * When an item is removed, its template instance is removed from the DOM.
|
27012
27112
|
* * When items are reordered, their respective templates are reordered in the DOM.
|
27013
27113
|
*
|
27014
|
-
*
|
27015
|
-
*
|
27016
|
-
*
|
27114
|
+
* To minimize creation of DOM elements, `ngRepeat` uses a function
|
27115
|
+
* to "keep track" of all items in the collection and their corresponding DOM elements.
|
27116
|
+
* For example, if an item is added to the collection, ngRepeat will know that all other items
|
27117
|
+
* already have DOM elements, and will not re-render them.
|
27118
|
+
*
|
27119
|
+
* The default tracking function (which tracks items by their identity) does not allow
|
27120
|
+
* duplicate items in arrays. This is because when there are duplicates, it is not possible
|
27121
|
+
* to maintain a one-to-one mapping between collection items and DOM elements.
|
27017
27122
|
*
|
27018
27123
|
* If you do need to repeat duplicate items, you can substitute the default tracking behavior
|
27019
27124
|
* with your own using the `track by` expression.
|
@@ -27026,7 +27131,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
|
|
27026
27131
|
* </div>
|
27027
27132
|
* ```
|
27028
27133
|
*
|
27029
|
-
* You may use arbitrary expressions in `track by`, including references to custom functions
|
27134
|
+
* You may also use arbitrary expressions in `track by`, including references to custom functions
|
27030
27135
|
* on the scope:
|
27031
27136
|
* ```html
|
27032
27137
|
* <div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)">
|
@@ -27034,10 +27139,14 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
|
|
27034
27139
|
* </div>
|
27035
27140
|
* ```
|
27036
27141
|
*
|
27037
|
-
*
|
27142
|
+
* <div class="alert alert-success">
|
27143
|
+
* If you are working with objects that have an identifier property, you should track
|
27038
27144
|
* by the identifier instead of the whole object. Should you reload your data later, `ngRepeat`
|
27039
27145
|
* will not have to rebuild the DOM elements for items it has already rendered, even if the
|
27040
|
-
* JavaScript objects in the collection have been substituted for new ones
|
27146
|
+
* JavaScript objects in the collection have been substituted for new ones. For large collections,
|
27147
|
+
* this signifincantly improves rendering performance. If you don't have a unique identifier,
|
27148
|
+
* `track by $index` can also provide a performance boost.
|
27149
|
+
* </div>
|
27041
27150
|
* ```html
|
27042
27151
|
* <div ng-repeat="model in collection track by model.id">
|
27043
27152
|
* {{model.name}}
|
@@ -28195,6 +28304,15 @@ var scriptDirective = ['$templateCache', function($templateCache) {
|
|
28195
28304
|
|
28196
28305
|
var noopNgModelController = { $setViewValue: noop, $render: noop };
|
28197
28306
|
|
28307
|
+
function chromeHack(optionElement) {
|
28308
|
+
// Workaround for https://code.google.com/p/chromium/issues/detail?id=381459
|
28309
|
+
// Adding an <option selected="selected"> element to a <select required="required"> should
|
28310
|
+
// automatically select the new element
|
28311
|
+
if (optionElement[0].hasAttribute('selected')) {
|
28312
|
+
optionElement[0].selected = true;
|
28313
|
+
}
|
28314
|
+
}
|
28315
|
+
|
28198
28316
|
/**
|
28199
28317
|
* @ngdoc type
|
28200
28318
|
* @name select.SelectController
|
@@ -28270,6 +28388,8 @@ var SelectController =
|
|
28270
28388
|
}
|
28271
28389
|
var count = optionsMap.get(value) || 0;
|
28272
28390
|
optionsMap.put(value, count + 1);
|
28391
|
+
self.ngModelCtrl.$render();
|
28392
|
+
chromeHack(element);
|
28273
28393
|
};
|
28274
28394
|
|
28275
28395
|
// Tell the select control that an option, with the given value, has been removed
|
@@ -28291,6 +28411,39 @@ var SelectController =
|
|
28291
28411
|
self.hasOption = function(value) {
|
28292
28412
|
return !!optionsMap.get(value);
|
28293
28413
|
};
|
28414
|
+
|
28415
|
+
|
28416
|
+
self.registerOption = function(optionScope, optionElement, optionAttrs, interpolateValueFn, interpolateTextFn) {
|
28417
|
+
|
28418
|
+
if (interpolateValueFn) {
|
28419
|
+
// The value attribute is interpolated
|
28420
|
+
var oldVal;
|
28421
|
+
optionAttrs.$observe('value', function valueAttributeObserveAction(newVal) {
|
28422
|
+
if (isDefined(oldVal)) {
|
28423
|
+
self.removeOption(oldVal);
|
28424
|
+
}
|
28425
|
+
oldVal = newVal;
|
28426
|
+
self.addOption(newVal, optionElement);
|
28427
|
+
});
|
28428
|
+
} else if (interpolateTextFn) {
|
28429
|
+
// The text content is interpolated
|
28430
|
+
optionScope.$watch(interpolateTextFn, function interpolateWatchAction(newVal, oldVal) {
|
28431
|
+
optionAttrs.$set('value', newVal);
|
28432
|
+
if (oldVal !== newVal) {
|
28433
|
+
self.removeOption(oldVal);
|
28434
|
+
}
|
28435
|
+
self.addOption(newVal, optionElement);
|
28436
|
+
});
|
28437
|
+
} else {
|
28438
|
+
// The value attribute is static
|
28439
|
+
self.addOption(optionAttrs.value, optionElement);
|
28440
|
+
}
|
28441
|
+
|
28442
|
+
optionElement.on('$destroy', function() {
|
28443
|
+
self.removeOption(optionAttrs.value);
|
28444
|
+
self.ngModelCtrl.$render();
|
28445
|
+
});
|
28446
|
+
};
|
28294
28447
|
}];
|
28295
28448
|
|
28296
28449
|
/**
|
@@ -28336,6 +28489,8 @@ var SelectController =
|
|
28336
28489
|
*
|
28337
28490
|
* @param {string} ngModel Assignable angular expression to data-bind to.
|
28338
28491
|
* @param {string=} name Property name of the form under which the control is published.
|
28492
|
+
* @param {string=} multiple Allows multiple options to be selected. The selected values will be
|
28493
|
+
* bound to the model as an array.
|
28339
28494
|
* @param {string=} required Sets `required` validation error key if the value is not entered.
|
28340
28495
|
* @param {string=} ngRequired Adds required attribute and required validation constraint to
|
28341
28496
|
* the element when the ngRequired expression evaluates to true. Use ngRequired instead of required
|
@@ -28501,7 +28656,13 @@ var selectDirective = function() {
|
|
28501
28656
|
restrict: 'E',
|
28502
28657
|
require: ['select', '?ngModel'],
|
28503
28658
|
controller: SelectController,
|
28504
|
-
|
28659
|
+
priority: 1,
|
28660
|
+
link: {
|
28661
|
+
pre: selectPreLink
|
28662
|
+
}
|
28663
|
+
};
|
28664
|
+
|
28665
|
+
function selectPreLink(scope, element, attr, ctrls) {
|
28505
28666
|
|
28506
28667
|
// if ngModel is not defined, we don't need to do anything
|
28507
28668
|
var ngModelCtrl = ctrls[1];
|
@@ -28571,7 +28732,6 @@ var selectDirective = function() {
|
|
28571
28732
|
|
28572
28733
|
}
|
28573
28734
|
}
|
28574
|
-
};
|
28575
28735
|
};
|
28576
28736
|
|
28577
28737
|
|
@@ -28579,16 +28739,6 @@ var selectDirective = function() {
|
|
28579
28739
|
// of dynamically created (and destroyed) option elements to their containing select
|
28580
28740
|
// directive via its controller.
|
28581
28741
|
var optionDirective = ['$interpolate', function($interpolate) {
|
28582
|
-
|
28583
|
-
function chromeHack(optionElement) {
|
28584
|
-
// Workaround for https://code.google.com/p/chromium/issues/detail?id=381459
|
28585
|
-
// Adding an <option selected="selected"> element to a <select required="required"> should
|
28586
|
-
// automatically select the new element
|
28587
|
-
if (optionElement[0].hasAttribute('selected')) {
|
28588
|
-
optionElement[0].selected = true;
|
28589
|
-
}
|
28590
|
-
}
|
28591
|
-
|
28592
28742
|
return {
|
28593
28743
|
restrict: 'E',
|
28594
28744
|
priority: 100,
|
@@ -28596,12 +28746,12 @@ var optionDirective = ['$interpolate', function($interpolate) {
|
|
28596
28746
|
|
28597
28747
|
if (isDefined(attr.value)) {
|
28598
28748
|
// If the value attribute is defined, check if it contains an interpolation
|
28599
|
-
var
|
28749
|
+
var interpolateValueFn = $interpolate(attr.value, true);
|
28600
28750
|
} else {
|
28601
28751
|
// If the value attribute is not defined then we fall back to the
|
28602
28752
|
// text content of the option element, which may be interpolated
|
28603
|
-
var
|
28604
|
-
if (!
|
28753
|
+
var interpolateTextFn = $interpolate(element.text(), true);
|
28754
|
+
if (!interpolateTextFn) {
|
28605
28755
|
attr.$set('value', element.text());
|
28606
28756
|
}
|
28607
28757
|
}
|
@@ -28615,44 +28765,8 @@ var optionDirective = ['$interpolate', function($interpolate) {
|
|
28615
28765
|
selectCtrl = parent.data(selectCtrlName) ||
|
28616
28766
|
parent.parent().data(selectCtrlName); // in case we are in optgroup
|
28617
28767
|
|
28618
|
-
|
28619
|
-
selectCtrl.
|
28620
|
-
selectCtrl.ngModelCtrl.$render();
|
28621
|
-
chromeHack(element);
|
28622
|
-
}
|
28623
|
-
|
28624
|
-
// Only update trigger option updates if this is an option within a `select`
|
28625
|
-
// that also has `ngModel` attached
|
28626
|
-
if (selectCtrl && selectCtrl.ngModelCtrl) {
|
28627
|
-
|
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
|
28640
|
-
scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
|
28641
|
-
attr.$set('value', newVal);
|
28642
|
-
if (oldVal !== newVal) {
|
28643
|
-
selectCtrl.removeOption(oldVal);
|
28644
|
-
}
|
28645
|
-
addOption(newVal);
|
28646
|
-
});
|
28647
|
-
} else {
|
28648
|
-
// The value attribute is static
|
28649
|
-
addOption(attr.value);
|
28650
|
-
}
|
28651
|
-
|
28652
|
-
element.on('$destroy', function() {
|
28653
|
-
selectCtrl.removeOption(attr.value);
|
28654
|
-
selectCtrl.ngModelCtrl.$render();
|
28655
|
-
});
|
28768
|
+
if (selectCtrl) {
|
28769
|
+
selectCtrl.registerOption(scope, element, attr, interpolateValueFn, interpolateTextFn);
|
28656
28770
|
}
|
28657
28771
|
};
|
28658
28772
|
}
|