aboutsummaryrefslogtreecommitdiffstats
path: root/alias-angular/app/lib/angular/angular.js
diff options
context:
space:
mode:
authorGuillaume Horel <guillaume.horel@gmail.com>2012-05-01 23:10:36 -0400
committerGuillaume Horel <guillaume.horel@gmail.com>2012-05-01 23:10:36 -0400
commit40c7d904c328179782745e8452be2a596d29c521 (patch)
tree7e39fb13f37d55ed0b2f2f18220dc65f898252e9 /alias-angular/app/lib/angular/angular.js
parent3fdb17a79de4507e8a4f3fbe47f6c078bdedda46 (diff)
downloadalias-40c7d904c328179782745e8452be2a596d29c521.tar.gz
bump angular to rc7
Diffstat (limited to 'alias-angular/app/lib/angular/angular.js')
-rw-r--r--alias-angular/app/lib/angular/angular.js427
1 files changed, 321 insertions, 106 deletions
diff --git a/alias-angular/app/lib/angular/angular.js b/alias-angular/app/lib/angular/angular.js
index b621c96..dca7169 100644
--- a/alias-angular/app/lib/angular/angular.js
+++ b/alias-angular/app/lib/angular/angular.js
@@ -1,6 +1,6 @@
/**
- * @license AngularJS v1.0.0rc5
- * (c) 2010-2012 AngularJS http://angularjs.org
+ * @license AngularJS v1.0.0rc7
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, document, undefined) {
@@ -8,9 +8,6 @@
////////////////////////////////////
-if (typeof document.getAttribute == 'undefined')
- document.getAttribute = function() {};
-
/**
* @ngdoc function
* @name angular.lowercase
@@ -1246,11 +1243,11 @@ function setupModuleLoader(window) {
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
*/
var version = {
- full: '1.0.0rc5', // all of these placeholder strings will be replaced by rake's
+ full: '1.0.0rc7', // all of these placeholder strings will be replaced by rake's
major: 1, // compile task
minor: 0,
dot: 0,
- codeName: 'reality-distortion'
+ codeName: 'rc-generation'
};
@@ -1308,6 +1305,7 @@ function publishExternalAPI(angular){
ngClass: ngClassDirective,
ngClassEven: ngClassEvenDirective,
ngClassOdd: ngClassOddDirective,
+ ngCsp: ngCspDirective,
ngCloak: ngCloakDirective,
ngController: ngControllerDirective,
ngForm: ngFormDirective,
@@ -1876,8 +1874,8 @@ function createEventHandler(element) {
// Remove monkey-patched methods (IE),
// as they would cause memory leaks in IE8.
- if (msie < 8) {
- // IE7 does not allow to delete property on native object
+ if (msie <= 8) {
+ // IE7/8 does not allow to delete property on native object
event.preventDefault = null;
event.stopPropagation = null;
event.isDefaultPrevented = null;
@@ -1921,14 +1919,12 @@ forEach({
bindFn(element, 'mouseover', function(event) {
counter++;
if (counter == 1) {
- event.type = 'mouseenter';
mouseenter(event);
}
});
bindFn(element, 'mouseout', function(event) {
counter --;
if (counter == 0) {
- event.type = 'mouseleave';
mouseleave(event);
}
});
@@ -3365,7 +3361,7 @@ function $TemplateCacheProvider() {
* Calling the linking function returns the element of the template. It is either the original element
* passed in, or the clone of the element if the `cloneAttachFn` is provided.
*
- * After linking the view is not updateh until after a call to $digest which typically is done by
+ * After linking the view is not updated until after a call to $digest which typically is done by
* Angular automatically.
*
* If you need access to the bound view, there are two ways to do it:
@@ -3742,12 +3738,17 @@ function $CompileProvider($provide) {
addTextInterpolateDirective(directives, node.nodeValue);
break;
case 8: /* Comment */
- match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);
- if (match) {
- nName = directiveNormalize(match[1]);
- if (addDirective(directives, nName, 'M', maxPriority)) {
- attrs[nName] = trim(match[2]);
+ try {
+ match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);
+ if (match) {
+ nName = directiveNormalize(match[1]);
+ if (addDirective(directives, nName, 'M', maxPriority)) {
+ attrs[nName] = trim(match[2]);
+ }
}
+ } catch (e) {
+ // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.
+ // Just ignore it and continue. (Can't seem to reproduce in test case.)
}
break;
}
@@ -5275,7 +5276,7 @@ var OPERATORS = {
};
var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
-function lex(text){
+function lex(text, csp){
var tokens = [],
token,
index = 0,
@@ -5435,7 +5436,7 @@ function lex(text){
if (OPERATORS.hasOwnProperty(ident)) {
token.fn = token.json = OPERATORS[ident];
} else {
- var getter = getterFn(ident);
+ var getter = getterFn(ident, csp);
token.fn = extend(function(self, locals) {
return (getter(self, locals));
}, {
@@ -5509,10 +5510,10 @@ function lex(text){
/////////////////////////////////////////
-function parser(text, json, $filter){
+function parser(text, json, $filter, csp){
var ZERO = valueFn(0),
value,
- tokens = lex(text),
+ tokens = lex(text, csp),
assignment = _assignment,
functionCall = _functionCall,
fieldAccess = _fieldAccess,
@@ -5780,7 +5781,7 @@ function parser(text, json, $filter){
function _fieldAccess(object) {
var field = expect().text;
- var getter = getterFn(field);
+ var getter = getterFn(field, csp);
return extend(
function(self, locals) {
return getter(object(self, locals), locals);
@@ -5933,32 +5934,119 @@ function getter(obj, path, bindFnToScope) {
var getterFnCache = {};
-function getterFn(path) {
+/**
+ * Implementation of the "Black Hole" variant from:
+ * - http://jsperf.com/angularjs-parse-getter/4
+ * - http://jsperf.com/path-evaluation-simplified/7
+ */
+function cspSafeGetterFn(key0, key1, key2, key3, key4) {
+ return function(scope, locals) {
+ var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,
+ promise;
+
+ if (!pathVal) return pathVal;
+
+ pathVal = pathVal[key0];
+ if (pathVal && pathVal.then) {
+ if (!("$$v" in pathVal)) {
+ promise = pathVal;
+ promise.$$v = undefined;
+ promise.then(function(val) { promise.$$v = val; });
+ }
+ pathVal = pathVal.$$v;
+ }
+ if (!key1 || !pathVal) return pathVal;
+
+ pathVal = pathVal[key1];
+ if (pathVal && pathVal.then) {
+ if (!("$$v" in pathVal)) {
+ promise = pathVal;
+ promise.$$v = undefined;
+ promise.then(function(val) { promise.$$v = val; });
+ }
+ pathVal = pathVal.$$v;
+ }
+ if (!key2 || !pathVal) return pathVal;
+
+ pathVal = pathVal[key2];
+ if (pathVal && pathVal.then) {
+ if (!("$$v" in pathVal)) {
+ promise = pathVal;
+ promise.$$v = undefined;
+ promise.then(function(val) { promise.$$v = val; });
+ }
+ pathVal = pathVal.$$v;
+ }
+ if (!key3 || !pathVal) return pathVal;
+
+ pathVal = pathVal[key3];
+ if (pathVal && pathVal.then) {
+ if (!("$$v" in pathVal)) {
+ promise = pathVal;
+ promise.$$v = undefined;
+ promise.then(function(val) { promise.$$v = val; });
+ }
+ pathVal = pathVal.$$v;
+ }
+ if (!key4 || !pathVal) return pathVal;
+
+ pathVal = pathVal[key4];
+ if (pathVal && pathVal.then) {
+ if (!("$$v" in pathVal)) {
+ promise = pathVal;
+ promise.$$v = undefined;
+ promise.then(function(val) { promise.$$v = val; });
+ }
+ pathVal = pathVal.$$v;
+ }
+ return pathVal;
+ };
+};
+
+function getterFn(path, csp) {
if (getterFnCache.hasOwnProperty(path)) {
return getterFnCache[path];
}
- var fn, code = 'var l, fn, p;\n';
- forEach(path.split('.'), function(key, index) {
- code += 'if(!s) return s;\n' +
- 'l=s;\n' +
- 's='+ (index
- // we simply direference 's' on any .dot notation
- ? 's'
- // but if we are first then we check locals firs, and if so read it first
- : '((k&&k.hasOwnProperty("' + key + '"))?k:s)') + '["' + key + '"]' + ';\n' +
- 'if (s && s.then) {\n' +
- ' if (!("$$v" in s)) {\n' +
- ' p=s;\n' +
- ' p.$$v = undefined;\n' +
- ' p.then(function(v) {p.$$v=v;});\n' +
- '}\n' +
- ' s=s.$$v\n' +
- '}\n';
- });
- code += 'return s;';
- fn = Function('s', 'k', code);
- fn.toString = function() { return code; };
+ var pathKeys = path.split('.'),
+ pathKeysLength = pathKeys.length,
+ fn;
+
+ if (csp) {
+ fn = (pathKeysLength < 6)
+ ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])
+ : function(scope, locals) {
+ var i = 0, val;
+ do {
+ val = cspSafeGetterFn(
+ pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]
+ )(scope, locals);
+ locals = undefined; // clear after first iteration
+ } while (i < pathKeysLength);
+ };
+ } else {
+ var code = 'var l, fn, p;\n';
+ forEach(pathKeys, function(key, index) {
+ code += 'if(!s) return s;\n' +
+ 'l=s;\n' +
+ 's='+ (index
+ // we simply dereference 's' on any .dot notation
+ ? 's'
+ // but if we are first then we check locals first, and if so read it first
+ : '((k&&k.hasOwnProperty("' + key + '"))?k:s)') + '["' + key + '"]' + ';\n' +
+ 'if (s && s.then) {\n' +
+ ' if (!("$$v" in s)) {\n' +
+ ' p=s;\n' +
+ ' p.$$v = undefined;\n' +
+ ' p.then(function(v) {p.$$v=v;});\n' +
+ '}\n' +
+ ' s=s.$$v\n' +
+ '}\n';
+ });
+ code += 'return s;';
+ fn = Function('s', 'k', code); // s=scope, k=locals
+ fn.toString = function() { return code; };
+ }
return getterFnCache[path] = fn;
}
@@ -5967,13 +6055,13 @@ function getterFn(path) {
function $ParseProvider() {
var cache = {};
- this.$get = ['$filter', function($filter) {
+ this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {
return function(exp) {
switch(typeof exp) {
case 'string':
return cache.hasOwnProperty(exp)
? cache[exp]
- : cache[exp] = parser(exp, false, $filter);
+ : cache[exp] = parser(exp, false, $filter, $sniffer.csp);
case 'function':
return exp;
default:
@@ -7549,7 +7637,9 @@ function $SnifferProvider() {
}
return eventSupport[event];
- }
+ },
+ // TODO(i): currently there is no way to feature detect CSP without triggering alerts
+ csp: false
};
}];
}
@@ -11264,7 +11354,7 @@ var ngValueDirective = [function() {
*
* Once scenario in which the use of `ngBind` is prefered over `{{ expression }}` binding is when
* it's desirable to put bindings into template that is momentarily displayed by the browser in its
- * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes make the
+ * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the
* bindings invisible to the user while the page is loading.
*
* An alternative solution to this problem would be using the
@@ -11371,10 +11461,10 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
* @description
* Creates a binding that will innerHTML the result of evaluating the `expression` into the current
* element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if
- * {@link angular.module.ng.$compileProvider.directive.ngBindHtml ngBindHtml} directive is too
+ * {@link angular.module.ngSanitize.directive.ngBindHtml ngBindHtml} directive is too
* restrictive and when you absolutely trust the source of the content you are binding to.
*
- * See {@link angular.module.ng.$sanitize $sanitize} docs for examples.
+ * See {@link angular.module.ngSanitize.$sanitize $sanitize} docs for examples.
*
* @element ANY
* @param {expression} ngBindHtmlUnsafe {@link guide/dev_guide.expressions Expression} to evaluate.
@@ -11694,6 +11784,32 @@ var ngControllerDirective = [function() {
/**
* @ngdoc directive
+ * @name angular.module.ng.$compileProvider.directive.ngCsp
+ * @priority 1000
+ *
+ * @description
+ * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
+ * This directive should be used on the root element of the application (typically the `<html>`
+ * element or other element with the {@link angular.module.ng.$compileProvider.directive.ngApp ngApp}
+ * directive).
+ *
+ * If enabled the performance of template expression evaluator will suffer slightly, so don't enable
+ * this mode unless you need it.
+ *
+ * @element html
+ */
+
+var ngCspDirective = ['$sniffer', function($sniffer) {
+ return {
+ priority: 1000,
+ compile: function() {
+ $sniffer.csp = true;
+ }
+ };
+}];
+
+/**
+ * @ngdoc directive
* @name angular.module.ng.$compileProvider.directive.ngClick
*
* @description
@@ -12982,8 +13098,11 @@ var scriptDirective = ['$templateCache', function($templateCache) {
terminal: true,
compile: function(element, attr) {
if (attr.type == 'text/ng-template') {
- var templateUrl = attr.id;
- $templateCache.put(templateUrl, element.text());
+ var templateUrl = attr.id,
+ // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent
+ text = element[0].text;
+
+ $templateCache.put(templateUrl, text);
}
}
};
@@ -13011,16 +13130,10 @@ var scriptDirective = ['$templateCache', function($templateCache) {
* be nested into the `<select>` element. This element will then represent `null` or "not selected"
* option. See example below for demonstration.
*
- * Note: `ngOptions` provides iterator facility for `<option>` element which must be used instead
- * of {@link angular.module.ng.$compileProvider.directive.ngRepeat ngRepeat}. `ngRepeat` is not
- * suitable for use with `<option>` element because of the following reasons:
- *
- * * value attribute of the option element that we need to bind to requires a string, but the
- * source of data for the iteration might be in a form of array containing objects instead of
- * strings
- * * {@link angular.module.ng.$compileProvider.directive.ngRepeat ngRepeat} unrolls after the
- * select binds causing incorect rendering on most browsers.
- * * binding to a value not in list confuses most browsers.
+ * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead
+ * of {@link angular.module.ng.$compileProvider.directive.ngRepeat ngRepeat} when you want the
+ * `select` model to be bound to a non-string value. This is because an option element can currently
+ * be bound to string values only.
*
* @param {string} name assignable expression to data-bind to.
* @param {string=} required The control is considered valid only if value is entered.
@@ -13081,11 +13194,11 @@ var scriptDirective = ['$templateCache', function($templateCache) {
<select ng-model="color" ng-options="c.name for c in colors"></select><br>
Color (null allowed):
- <div class="nullable">
+ <span class="nullable">
<select ng-model="color" ng-options="c.name for c in colors">
<option value="">-- chose color --</option>
</select>
- </div><br/>
+ </span><br/>
Color grouped by shade:
<select ng-model="color" ng-options="c.name group by c.shade for c in colors">
@@ -13115,49 +13228,136 @@ var scriptDirective = ['$templateCache', function($templateCache) {
var ngOptionsDirective = valueFn({ terminal: true });
var selectDirective = ['$compile', '$parse', function($compile, $parse) {
//00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777
- var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*)$/;
+ var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*)$/,
+ nullModelCtrl = {$setViewValue: noop};
return {
restrict: 'E',
- require: '?ngModel',
- link: function(scope, element, attr, ctrl) {
- if (!ctrl) return;
+ require: ['select', '?ngModel'],
+ controller: ['$element', '$scope', function($element, $scope) {
+ var self = this,
+ optionsMap = {},
+ ngModelCtrl = nullModelCtrl,
+ nullOption,
+ unknownOption;
- var multiple = attr.multiple,
- optionsExp = attr.ngOptions;
+ self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {
+ ngModelCtrl = ngModelCtrl_;
+ nullOption = nullOption_;
+ unknownOption = unknownOption_;
+ }
+
+
+ self.addOption = function(value) {
+ optionsMap[value] = true;
+
+ if (ngModelCtrl.$viewValue == value) {
+ $element.val(value);
+ if (unknownOption.parent()) unknownOption.remove();
+ }
+ };
+
+
+ self.removeOption = function(value) {
+ if (this.hasOption(value)) {
+ delete optionsMap[value];
+ if (ngModelCtrl.$viewValue == value) {
+ this.renderUnknownOption(value);
+ }
+ }
+ };
+
+
+ self.renderUnknownOption = function(val) {
+ var unknownVal = '? ' + hashKey(val) + ' ?';
+ unknownOption.val(unknownVal);
+ $element.prepend(unknownOption);
+ $element.val(unknownVal);
+ unknownOption.prop('selected', true); // needed for IE
+ }
+
+
+ self.hasOption = function(value) {
+ return optionsMap.hasOwnProperty(value);
+ }
+
+ $scope.$on('$destroy', function() {
+ // disable unknown option so that we don't do work when the whole select is being destroyed
+ self.renderUnknownOption = noop;
+ });
+ }],
+
+ link: function(scope, element, attr, ctrls) {
+ // if ngModel is not defined, we don't need to do anything
+ if (!ctrls[1]) return;
+
+ var selectCtrl = ctrls[0],
+ ngModelCtrl = ctrls[1],
+ multiple = attr.multiple,
+ optionsExp = attr.ngOptions,
+ nullOption = false, // if false, user will not be able to select it (used by ngOptions)
+ emptyOption,
+ // we can't just jqLite('<option>') since jqLite is not smart enough
+ // to create it in <select> and IE barfs otherwise.
+ optionTemplate = jqLite(document.createElement('option')),
+ optGroupTemplate =jqLite(document.createElement('optgroup')),
+ unknownOption = optionTemplate.clone();
+
+ // find "null" option
+ for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {
+ if (children[i].value == '') {
+ emptyOption = nullOption = children.eq(i);
+ break;
+ }
+ }
+
+ selectCtrl.init(ngModelCtrl, nullOption, unknownOption);
// required validator
if (multiple && (attr.required || attr.ngRequired)) {
var requiredValidator = function(value) {
- ctrl.$setValidity('required', !attr.required || (value && value.length));
+ ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));
return value;
};
- ctrl.$parsers.push(requiredValidator);
- ctrl.$formatters.unshift(requiredValidator);
+ ngModelCtrl.$parsers.push(requiredValidator);
+ ngModelCtrl.$formatters.unshift(requiredValidator);
attr.$observe('required', function() {
- requiredValidator(ctrl.$viewValue);
+ requiredValidator(ngModelCtrl.$viewValue);
});
}
- if (optionsExp) Options(scope, element, ctrl);
- else if (multiple) Multiple(scope, element, ctrl);
- else Single(scope, element, ctrl);
+ if (optionsExp) Options(scope, element, ngModelCtrl);
+ else if (multiple) Multiple(scope, element, ngModelCtrl);
+ else Single(scope, element, ngModelCtrl, selectCtrl);
////////////////////////////
- function Single(scope, selectElement, ctrl) {
- ctrl.$render = function() {
- selectElement.val(ctrl.$viewValue);
+ function Single(scope, selectElement, ngModelCtrl, selectCtrl) {
+ ngModelCtrl.$render = function() {
+ var viewValue = ngModelCtrl.$viewValue;
+
+ if (selectCtrl.hasOption(viewValue)) {
+ if (unknownOption.parent()) unknownOption.remove();
+ selectElement.val(viewValue);
+ if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy
+ } else {
+ if (isUndefined(viewValue) && emptyOption) {
+ selectElement.val('');
+ } else {
+ selectCtrl.renderUnknownOption(viewValue);
+ }
+ }
};
selectElement.bind('change', function() {
scope.$apply(function() {
- ctrl.$setViewValue(selectElement.val());
+ if (unknownOption.parent()) unknownOption.remove();
+ ngModelCtrl.$setViewValue(selectElement.val());
});
});
}
@@ -13208,26 +13408,26 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
groupByFn = $parse(match[3] || ''),
valueFn = $parse(match[2] ? match[1] : valueName),
valuesFn = $parse(match[7]),
- // we can't just jqLite('<option>') since jqLite is not smart enough
- // to create it in <select> and IE barfs otherwise.
- optionTemplate = jqLite(document.createElement('option')),
- optGroupTemplate = jqLite(document.createElement('optgroup')),
- nullOption = false, // if false then user will not be able to select it
// This is an array of array of existing option groups in DOM. We try to reuse these if possible
// optionGroupsCache[0] is the options with no option group
// optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element
optionGroupsCache = [[{element: selectElement, label:''}]];
- // find existing special options
- forEach(selectElement.children(), function(option) {
- if (option.value == '') {
- // developer declared null option, so user should be able to select it
- nullOption = jqLite(option).remove();
- // compile the element since there might be bindings in it
- $compile(nullOption)(scope);
- }
- });
- selectElement.html(''); // clear contents
+ if (nullOption) {
+ // compile the element since there might be bindings in it
+ $compile(nullOption)(scope);
+
+ // remove the class, which is added automatically because we recompile the element and it
+ // becomes the compilation root
+ nullOption.removeClass('ng-scope');
+
+ // we need to remove it before calling selectElement.html('') because otherwise IE will
+ // remove the label from the element. wtf?
+ nullOption.remove();
+ }
+
+ // clear contents, we'll add what's needed based on the model
+ selectElement.html('');
selectElement.bind('change', function() {
scope.$apply(function() {
@@ -13239,8 +13439,8 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
if (multiple) {
value = [];
for (groupIndex = 0, groupLength = optionGroupsCache.length;
- groupIndex < groupLength;
- groupIndex++) {
+ groupIndex < groupLength;
+ groupIndex++) {
// list of options for that group. (first item has the parent)
optionGroup = optionGroupsCache[groupIndex];
@@ -13354,7 +13554,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
}
}
- lastElement = null; // start at the begining
+ lastElement = null; // start at the beginning
for(index = 0, length = optionGroup.length; index < length; index++) {
option = optionGroup[index];
if ((existingOption = existingOptions[index+1])) {
@@ -13420,19 +13620,34 @@ var optionDirective = ['$interpolate', function($interpolate) {
return {
restrict: 'E',
priority: 100,
+ require: '^select',
compile: function(element, attr) {
if (isUndefined(attr.value)) {
var interpolateFn = $interpolate(element.text(), true);
- if (interpolateFn) {
- return function (scope, element, attr) {
- scope.$watch(interpolateFn, function(value) {
- attr.$set('value', value);
- });
- }
- } else {
+ if (!interpolateFn) {
attr.$set('value', element.text());
}
}
+
+ // For some reason Opera defaults to true and if not overridden this messes up the repeater.
+ // We don't want the view to drive the initialization of the model anyway.
+ element.prop('selected', false);
+
+ return function (scope, element, attr, selectCtrl) {
+ if (interpolateFn) {
+ scope.$watch(interpolateFn, function(newVal, oldVal) {
+ attr.$set('value', newVal);
+ if (newVal !== oldVal) selectCtrl.removeOption(oldVal);
+ selectCtrl.addOption(newVal);
+ });
+ } else {
+ selectCtrl.addOption(attr.value);
+ }
+
+ element.bind('$destroy', function() {
+ selectCtrl.removeOption(attr.value);
+ });
+ };
}
}
}];