diff --git a/src/lib/annotations/annotations.html b/src/lib/annotations/annotations.html index 790faf218b..663a7ab8f1 100644 --- a/src/lib/annotations/annotations.html +++ b/src/lib/annotations/annotations.html @@ -156,7 +156,9 @@ var annote = { bindings: [{ kind: 'text', - parts: parts + name: 'textContent', + parts: parts, + isCompound: parts.length !== 1 }] }; list.push(annote); diff --git a/src/lib/bind/effects.html b/src/lib/bind/effects.html index b605664395..ceeb3fdf70 100644 --- a/src/lib/bind/effects.html +++ b/src/lib/bind/effects.html @@ -20,6 +20,10 @@ !effect.parts[0].negate; }, + _compoundInitializationEffect: function(source, value, effect) { + this._applyEffectValue(effect); + }, + _annotationEffect: function(source, value, effect) { if (source != effect.value) { value = this._get(effect.value); @@ -30,7 +34,7 @@ // are used, since the target element may not dirty check (e.g. ) if (!effect.customEvent || this._nodes[effect.index][effect.name] !== calc) { - return this._applyEffectValue(calc, effect); + return this._applyEffectValue(effect, calc); } }, @@ -95,7 +99,7 @@ if (effect.negate) { computedvalue = !computedvalue; } - this._applyEffectValue(computedvalue, effect); + this._applyEffectValue(effect, computedvalue); } } else { computedHost._warn(computedHost._logf('_annotatedComputationEffect', diff --git a/src/standard/annotations.html b/src/standard/annotations.html index 4842f71346..8e969de4c8 100644 --- a/src/standard/annotations.html +++ b/src/standard/annotations.html @@ -221,6 +221,7 @@ // push configuration references at configure time _configureAnnotationReferences: function() { this._configureTemplateContent(); + this._configureCompoundBindings(); }, // nested template contents have been stored prototypically to avoid @@ -236,6 +237,26 @@ }, this); }, + // Compound bindings utilize private storage on the node to store + // the current state of each value that will be concatenated to generate + // the final property/attribute/text value + // Here we initialize the private storage array on the node with any + // literal parts that won't change (could get fancy and use WeakMap) + _configureCompoundBindings: function() { + this._notes.forEach(function(note, i) { + var node = this._nodes[i]; + note.bindings.forEach(function(binding) { + if (binding.isCompound) { + var storage = node.__compoundStorage__ || + (node.__compoundStorage__ = {}); + storage[binding.name] = binding.parts.map(function(part) { + return part.literal; + }); + } + }); + }, this); + }, + // construct `$` map (from id annotations) _marshalIdNodes: function() { this.$ = {}; diff --git a/src/standard/effectBuilder.html b/src/standard/effectBuilder.html index b976fefc12..cd35fd9803 100644 --- a/src/standard/effectBuilder.html +++ b/src/standard/effectBuilder.html @@ -150,6 +150,14 @@ }); } } + // We need to ensure compound bindings with literals push the literals + // through regardless of whether annotation dependencies initialized + // this is done with a special compoundInitialization effect which simply + // kicks _applyEffectValue to push the literals through + if (note.isCompound) { + note.index = index; + this._addPropertyEffect('__static__', 'compoundInitialization', note); + } }, _addAnnotatedComputationEffect: function(note, part, index) { @@ -262,11 +270,14 @@ Polymer.Bind.setupBindListeners(this); }, - _applyEffectValue: function(value, info) { + _applyEffectValue: function(info, value) { var node = this._nodes[info.index]; - // TODO(sorvell): ideally, the info object is normalized for easy - // lookup here. - var property = info.name || 'textContent'; + var property = info.name; + if (info.isCompound) { + var storage = node.__compoundStorage__[property]; + storage[info.compoundIndex] = value; + value = storage.join(''); + } // special processing for 'class' and 'className'; 'class' handled // when attr is serialized. if (info.kind == 'attribute') { diff --git a/test/unit/bind-elements.html b/test/unit/bind-elements.html index 250feae712..129997a7f6 100644 --- a/test/unit/bind-elements.html +++ b/test/unit/bind-elements.html @@ -24,6 +24,10 @@ computed-from-tricky-literals2='{{computeFromTrickyLiterals(3,"tricky\,'zot'" )}}' computed-from-no-args="{{computeFromNoArgs( )}}" no-computed="{{foobared(noInlineComputed)}}" + compound1="{{cpnd1}}{{ cpnd2 }}{{cpnd3.prop}}{{ computeCompound(cpnd4, cpnd5, 'literal')}}" + compound2="literal1 {{cpnd1}} literal2 {{cpnd2}}{{cpnd3.prop}} literal3 {{computeCompound(cpnd4, cpnd5, 'literal')}} literal4" + compoundAttr1$="{{cpnd1}}{{ cpnd2 }}{{cpnd3.prop}}{{ computeCompound(cpnd4, cpnd5, 'literal')}}" + compoundAttr2$="literal1 {{cpnd1}} literal2 {{cpnd2}}{{cpnd3.prop}} literal3 {{computeCompound(cpnd4, cpnd5, 'literal')}} literal4" > Test @@ -31,6 +35,10 @@ {{computeFromTrickyLiterals(3, 'tricky\,\'zot\'')}} +
{{cpnd1}}{{cpnd2}}{{cpnd3.prop}}{{computeCompound(cpnd4, cpnd5, 'literal')}}
+
+ literal1 {{cpnd1}} literal2 {{cpnd2}}{{cpnd3.prop}} literal3 {{computeCompound(cpnd4, cpnd5, 'literal')}} literal4 +
diff --git a/test/unit/bind.html b/test/unit/bind.html index 3a003841f4..261643605b 100644 --- a/test/unit/bind.html +++ b/test/unit/bind.html @@ -688,22 +688,115 @@ }); - +suite('binding corner cases', function() { - +}); +