aboutsummaryrefslogtreecommitdiffstats
path: root/src/service/compiler.js
diff options
context:
space:
mode:
authorVojta Jina2012-02-15 11:34:56 -0800
committerMisko Hevery2012-02-21 22:46:01 -0800
commit6d0ca95fa05ea6c7bcaef5c1d5a03fa67a6b6d0c (patch)
tree8ebb7303af4783c2a388102680a96d7339a13e51 /src/service/compiler.js
parent3df7b8e57f125160738a811e97ca7819a78c48ff (diff)
downloadangular.js-6d0ca95fa05ea6c7bcaef5c1d5a03fa67a6b6d0c.tar.bz2
feat($compiler): Allow attr.$observe() interpolated attrs
Diffstat (limited to 'src/service/compiler.js')
-rw-r--r--src/service/compiler.js96
1 files changed, 63 insertions, 33 deletions
diff --git a/src/service/compiler.js b/src/service/compiler.js
index ef049b50..43db1e9b 100644
--- a/src/service/compiler.js
+++ b/src/service/compiler.js
@@ -281,7 +281,9 @@ function $CompileProvider($provide) {
attrs = {
$attr: {},
$normalize: directiveNormalize,
- $set: attrSetter
+ $set: attrSetter,
+ $observe: interpolatedAttrObserve,
+ $observers: {}
};
// we must always refer to nodeList[i] since the nodes can be replaced underneath us.
directives = collectDirectives(nodeList[i], [], attrs, maxPriority);
@@ -861,6 +863,10 @@ function $CompileProvider($provide) {
compile: function(element, attr) {
if (interpolateFn) {
return function(scope, element, attr) {
+ // we define observers array only for interpolated attrs
+ // and ignore observers for non interpolated attrs to save some memory
+ attr.$observers[name] = [];
+ attr[name] = undefined;
scope.$watch(interpolateFn, function(value) {
attr.$set(name, value);
});
@@ -900,45 +906,69 @@ function $CompileProvider($provide) {
}
element[0] = newNode;
}
- }];
- /**
- * Set a normalized attribute on the element in a way such that all directives
- * can share the attribute. This function properly handles boolean attributes.
- * @param {string} key Normalized key. (ie ngAttribute)
- * @param {string|boolean} value The value to set. If `null` attribute will be deleted.
- * @param {string=} attrName Optional none normalized name. Defaults to key.
- */
- function attrSetter(key, value, attrName) {
- var booleanKey = BOOLEAN_ATTR[key.toLowerCase()];
-
- if (booleanKey) {
- value = toBoolean(value);
- this.$element.prop(key, value);
- this[key] = value;
- attrName = key = booleanKey;
- value = value ? booleanKey : undefined;
- } else {
- this[key] = value;
- }
+ /**
+ * Set a normalized attribute on the element in a way such that all directives
+ * can share the attribute. This function properly handles boolean attributes.
+ * @param {string} key Normalized key. (ie ngAttribute)
+ * @param {string|boolean} value The value to set. If `null` attribute will be deleted.
+ * @param {string=} attrName Optional none normalized name. Defaults to key.
+ */
+ function attrSetter(key, value, attrName) {
+ var booleanKey = BOOLEAN_ATTR[key.toLowerCase()];
+
+ if (booleanKey) {
+ value = toBoolean(value);
+ this.$element.prop(key, value);
+ this[key] = value;
+ attrName = key = booleanKey;
+ value = value ? booleanKey : undefined;
+ } else {
+ this[key] = value;
+ }
- // translate normalized key to actual key
- if (attrName) {
- this.$attr[key] = attrName;
- } else {
- attrName = this.$attr[key];
- if (!attrName) {
- this.$attr[key] = attrName = snake_case(key, '-');
+ // translate normalized key to actual key
+ if (attrName) {
+ this.$attr[key] = attrName;
+ } else {
+ attrName = this.$attr[key];
+ if (!attrName) {
+ this.$attr[key] = attrName = snake_case(key, '-');
+ }
+ }
+
+ if (value === null || value === undefined) {
+ this.$element.removeAttr(attrName);
+ } else {
+ this.$element.attr(attrName, value);
}
+
+ // fire observers
+ forEach(this.$observers[key], function(fn) {
+ try {
+ fn(value);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ });
}
- if (value === null || value === undefined) {
- this.$element.removeAttr(attrName);
- } else {
- this.$element.attr(attrName, value);
+
+ /**
+ * Observe an interpolated attribute.
+ * The observer will never be called, if given attribute is not interpolated.
+ *
+ * @param {string} key Normalized key. (ie ngAttribute) .
+ * @param {function(*)} fn Function that will be called whenever the attribute value changes.
+ */
+ function interpolatedAttrObserve(key, fn) {
+ // keep only observers for interpolated attrs
+ if (this.$observers[key]) {
+ this.$observers[key].push(fn);
+ }
}
- }
+ }];
}
var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i;