angularjs-rails 1.4.7 → 1.4.8
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 +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
|
}
|