From 9be82d942fc6ab2772197c84a35a4c374c604cbc Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Mon, 4 Jun 2012 15:06:02 -0700 Subject: refactor($compile): always call attr.$observe attr.$observe used to call function only if there was interpolation on that attribute. We now call the observation function all the time but we only save the reference to it if interpolation is present. --- src/ng/compile.js | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'src/ng/compile.js') diff --git a/src/ng/compile.js b/src/ng/compile.js index 0d9ff9ea..ee120263 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -221,9 +221,9 @@ function $CompileProvider($provide) { this.$get = [ '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse', - '$controller', + '$controller', '$rootScope', function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse, - $controller) { + $controller, $rootScope) { var LOCAL_MODE = { attribute: function(localName, mode, parentScope, scope, attr) { @@ -268,7 +268,6 @@ function $CompileProvider($provide) { var Attributes = function(element, attr) { this.$$element = element; - this.$$observers = {}; this.$attr = attr || {}; }; @@ -286,7 +285,8 @@ function $CompileProvider($provide) { * @param {string=} attrName Optional none normalized name. Defaults to key. */ $set: function(key, value, writeAttr, attrName) { - var booleanKey = getBooleanAttrName(this.$$element[0], key); + var booleanKey = getBooleanAttrName(this.$$element[0], key), + $$observers = this.$$observers; if (booleanKey) { this.$$element.prop(key, value); @@ -314,7 +314,7 @@ function $CompileProvider($provide) { } // fire observers - forEach(this.$$observers[key], function(fn) { + $$observers && forEach($$observers[key], function(fn) { try { fn(value); } catch (e) { @@ -333,10 +333,17 @@ function $CompileProvider($provide) { * @returns {function(*)} the `fn` Function passed in. */ $observe: function(key, fn) { - // keep only observers for interpolated attrs - if (this.$$observers[key]) { - this.$$observers[key].push(fn); - } + var attrs = this, + $$observers = (attrs.$$observers || (attrs.$$observers = {})), + listeners = ($$observers[key] || ($$observers[key] = [])); + + listeners.push(fn); + $rootScope.$evalAsync(function() { + if (!listeners.$$inter) { + // no one registered attribute interpolation function, so lets call it manually + fn(attrs[key]); + } + }); return fn; } }; @@ -990,16 +997,16 @@ function $CompileProvider($provide) { directives.push({ priority: 100, compile: valueFn(function(scope, element, attr) { + var $$observers = (attr.$$observers || (attr.$$observers = {})); + if (name === 'class') { // we need to interpolate classes again, in the case the element was replaced // and therefore the two class attrs got merged - we want to interpolate the result interpolateFn = $interpolate(attr[name], true); } - // 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; + ($$observers[name] || ($$observers[name] = [])).$$inter = true; scope.$watch(interpolateFn, function(value) { attr.$set(name, value); }); -- cgit v1.2.3