From 6d98251fb8033db9607e4b1f4efba410fb2a6d72 Mon Sep 17 00:00:00 2001 From: Rafael Weinstein Date: Tue, 3 Sep 2013 17:42:06 -0700 Subject: [PATCH] getBinding -> prepareBinding/bindingFn R=arv BUG= Review URL: https://codereview.appspot.com/13366047 --- src/TemplateBinding.js | 108 ++++++++++++++++++++------------------- tests/tests.js | 112 +++++++++++++++++++++++++---------------- 2 files changed, 124 insertions(+), 96 deletions(-) diff --git a/src/TemplateBinding.js b/src/TemplateBinding.js index d7a0a93..3cdadb0 100644 --- a/src/TemplateBinding.js +++ b/src/TemplateBinding.js @@ -470,21 +470,19 @@ var content = this.ref.content; var map = content.bindingMap_; if (!map) { + var delegatePrepareBindingFn = + delegate && typeof delegate.prepareBinding === 'function' ? + delegate.prepareBinding : undefined; // TODO(rafaelw): Setup a MutationObserver on content to detect // when the instanceMap is invalid. - map = createInstanceBindingMap(content) || []; + map = createInstanceBindingMap(content, delegatePrepareBindingFn) || []; content.bindingMap_ = map; } var instance = map.hasSubTemplate ? deepCloneIgnoreTemplateContent(content) : content.cloneNode(true); - var delegateGetBindingFn = - delegate && typeof delegate.getBinding === 'function' ? - delegate.getBinding : undefined; - - addMapBindings(instance, map, model, delegate, delegateGetBindingFn, - bound); + addMapBindings(instance, map, model, delegate, bound); // TODO(rafaelw): We can do this more lazily, but setting a sentinel // in the parent of the template element, and creating it when it's // asked for by walking back to find the iterating template. @@ -532,8 +530,8 @@ // Returns // a) undefined if there are no mustaches. - // b) [TEXT, (PATH, TEXT)+] if there is at least one mustache. - function parseMustaches(s) { + // b) [TEXT, (PATH, DELEGATE_FN, TEXT)+] if there is at least one mustache. + function parseMustaches(s, name, node, delegatePrepareBindingFn) { if (!s || !s.length) return; @@ -554,26 +552,30 @@ tokens = tokens || []; tokens.push(s.slice(lastIndex, startIndex)); // TEXT - tokens.push(s.slice(startIndex + 2, endIndex).trim()); // PATH + var pathString = s.slice(startIndex + 2, endIndex).trim(); + tokens.push(Path.get(pathString)); // PATH + var delegateFn = delegatePrepareBindingFn && + delegatePrepareBindingFn(pathString, name, node) + tokens.push(delegateFn); // DELEGATE_FN lastIndex = endIndex + 2; } if (lastIndex === length) tokens.push(''); // TEXT - tokens.hasOnePath = tokens.length === 3; + tokens.hasOnePath = tokens.length === 4; tokens.isSimplePath = tokens.hasOnePath && tokens[0] == '' && - tokens[2] == ''; + tokens[3] == ''; tokens.combinator = function(values) { var newValue = tokens[0]; - for (var i = 1; i < tokens.length; i += 2) { - var value = tokens.hasOnePath ? values : values[(i-1)/ 2]; + for (var i = 1; i < tokens.length; i += 3) { + var value = tokens.hasOnePath ? values : values[(i - 1) / 3]; if (value !== undefined) newValue += value; - newValue += tokens[i + 1]; + newValue += tokens[i + 2]; } return newValue; @@ -582,20 +584,21 @@ return tokens; } - function processBindings(bindings, node, model, delegateGetBindingFn, bound) { + var valuePath = Path.get('value'); + + function processBindings(bindings, node, model, bound) { for (var i = 0; i < bindings.length; i += 2) { var name = bindings[i]; var tokens = bindings[i + 1]; var bindingModel = model; var bindingPath = tokens[1]; if (tokens.hasOnePath) { - var dm = delegateGetBindingFn && delegateGetBindingFn(bindingModel, - bindingPath, - name, - node); - if (dm !== undefined) { - bindingModel = dm; - bindingPath = 'value'; + var delegateFn = tokens[2]; + var delegateBinding = delegateFn && delegateFn(model, name, node); + + if (delegateBinding !== undefined) { + bindingModel = delegateBinding; + bindingPath = valuePath; } if (!tokens.isSimplePath) { @@ -603,7 +606,7 @@ undefined, undefined, tokens.combinator); - bindingPath = 'value'; + bindingPath = valuePath; } } else { var observer = new CompoundPathObserver(undefined, @@ -612,16 +615,15 @@ tokens.combinator); - for (var i = 1; i < tokens.length; i = i + 2) { + for (var i = 1; i < tokens.length; i = i + 3) { var subModel = model; var subPath = tokens[i]; - var dm = delegateGetBindingFn && delegateGetBindingFn(subModel, - subPath, - name, - node); - if (dm !== undefined) { - subModel = dm; - subPath = 'value'; + var delegateFn = tokens[i + 1]; + var delegateBinding = delegateFn && delegateFn(subModel, name, node); + + if (delegateBinding !== undefined) { + subModel = delegateBinding; + subPath = valuePath; } observer.addPath(subModel, subPath); @@ -629,7 +631,7 @@ observer.start(); bindingModel = observer; - bindingPath = 'value'; + bindingPath = valuePath; } var binding = node.bind(name, bindingModel, bindingPath); @@ -638,7 +640,7 @@ } } - function parseAttributeBindings(element) { + function parseAttributeBindings(element, delegatePrepareBindingFn) { assert(element); var bindings; @@ -661,7 +663,8 @@ } } - var tokens = parseMustaches(value); + var tokens = parseMustaches(value, name, element, + delegatePrepareBindingFn); if (!tokens) continue; @@ -672,25 +675,26 @@ // Treat