Skip to content

Commit

Permalink
Apply effect value from compound parts.
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinpschaaf committed Oct 10, 2015
1 parent 1026498 commit c30ac10
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 17 deletions.
4 changes: 3 additions & 1 deletion src/lib/annotations/annotations.html
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,9 @@
var annote = {
bindings: [{
kind: 'text',
parts: parts
name: 'textContent',
parts: parts,
isCompound: parts.length !== 1
}]
};
list.push(annote);
Expand Down
8 changes: 6 additions & 2 deletions src/lib/bind/effects.html
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -30,7 +34,7 @@
// are used, since the target element may not dirty check (e.g. <input>)
if (!effect.customEvent ||
this._nodes[effect.index][effect.name] !== calc) {
return this._applyEffectValue(calc, effect);
return this._applyEffectValue(effect, calc);
}
},

Expand Down Expand Up @@ -95,7 +99,7 @@
if (effect.negate) {
computedvalue = !computedvalue;
}
this._applyEffectValue(computedvalue, effect);
this._applyEffectValue(effect, computedvalue);
}
} else {
computedHost._warn(computedHost._logf('_annotatedComputationEffect',
Expand Down
21 changes: 21 additions & 0 deletions src/standard/annotations.html
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.$ = {};
Expand Down
19 changes: 15 additions & 4 deletions src/standard/effectBuilder.html
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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') {
Expand Down
11 changes: 11 additions & 0 deletions test/unit/bind-elements.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,21 @@
computed-from-tricky-literals2='{{computeFromTrickyLiterals(3,"tricky\,&#39;zot&#39;" )}}'
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
</div>
<span id="boundText">{{text}}</span>
<span idtest id="{{boundId}}"></span>
<s id="computedContent">{{computeFromTrickyLiterals(3, 'tricky\,\'zot\'')}}</s>
<input id="boundInput" value="{{text::input}}">
<div id="compound1">{{cpnd1}}{{cpnd2}}{{cpnd3.prop}}{{computeCompound(cpnd4, cpnd5, 'literal')}}</div>
<div id="compound2">
literal1 {{cpnd1}} literal2 {{cpnd2}}{{cpnd3.prop}} literal3 {{computeCompound(cpnd4, cpnd5, 'literal')}} literal4
</div>
</template>
<script>
Polymer({
Expand Down Expand Up @@ -237,6 +245,9 @@
},
computeNegativeNumber: function (num) {
return num;
},
computeCompound: function(a, b, c) {
return '' + c + b + a;
}
});
</script>
Expand Down
113 changes: 103 additions & 10 deletions test/unit/bind.html
Original file line number Diff line number Diff line change
Expand Up @@ -688,22 +688,115 @@

});

</script>
suite('binding corner cases', function() {

<script>
suite('binding corner cases', function() {
// IE can create adjacent text nodes that split bindings; this test
// ensures the code that addresses this is functional
test('text binding after entity', function() {
var el = document.createElement('x-entity-and-binding');
assert.equal(el.$.binding.textContent, 'binding');
});

// IE can create adjacent text nodes that split bindings; this test
// ensures the code that addresses this is functional
test('text binding after entity', function() {
var el = document.createElement('x-entity-and-binding');
assert.equal(el.$.binding.textContent, 'binding');
});
});

suite('compound binding / string interpolation', function() {

test('compound adjacent property bindings', function() {
var el = document.createElement('x-basic');
assert.equal(el.$.boundChild.compound1, '');
el.cpnd2 = 'cpnd2';
assert.equal(el.$.boundChild.compound1, 'cpnd2');
el.cpnd1 = 'cpnd1';
el.cpnd3 = {prop: 'cpnd3'};
assert.equal(el.$.boundChild.compound1, 'cpnd1cpnd2cpnd3');
el.cpnd4 = 'cpnd4';
assert.equal(el.$.boundChild.compound1, 'cpnd1cpnd2cpnd3');
el.cpnd5 = 'cpnd5';
assert.equal(el.$.boundChild.compound1, 'cpnd1cpnd2cpnd3literalcpnd5cpnd4');
});

test('compound property bindings with literals', function() {
var el = document.createElement('x-basic');
assert.equal(el.$.boundChild.compound2, 'literal1 literal2 literal3 literal4');
el.cpnd1 = 'cpnd1';
el.cpnd2 = 'cpnd2';
el.cpnd3 = {prop: 'cpnd3'};
el.cpnd4 = 'cpnd4';
el.cpnd5 = 'cpnd5';
assert.equal(el.$.boundChild.compound2, 'literal1 cpnd1 literal2 cpnd2cpnd3 literal3 literalcpnd5cpnd4 literal4');
el.cpnd1 = null;
el.cpnd2 = undefined;
el.cpnd3 = {};
el.cpnd4 = '';
el.cpnd5 = '';
assert.equal(el.$.boundChild.compound2, 'literal1 literal2 literal3 literal literal4');
});

test('compound adjacent property bindings', function() {
var el = document.createElement('x-basic');
assert.equal(el.$.boundChild.getAttribute('compoundAttr1'), '');
el.cpnd2 = 'cpnd2';
assert.equal(el.$.boundChild.getAttribute('compoundAttr1'), 'cpnd2');
el.cpnd1 = 'cpnd1';
el.cpnd3 = {prop: 'cpnd3'};
assert.equal(el.$.boundChild.getAttribute('compoundAttr1'), 'cpnd1cpnd2cpnd3');
el.cpnd4 = 'cpnd4';
assert.equal(el.$.boundChild.getAttribute('compoundAttr1'), 'cpnd1cpnd2cpnd3');
el.cpnd5 = 'cpnd5';
assert.equal(el.$.boundChild.getAttribute('compoundAttr1'), 'cpnd1cpnd2cpnd3literalcpnd5cpnd4');
});

test('compound property bindings with literals', function() {
var el = document.createElement('x-basic');
assert.equal(el.$.boundChild.getAttribute('compoundAttr2'), 'literal1 literal2 literal3 literal4');
el.cpnd1 = 'cpnd1';
el.cpnd2 = 'cpnd2';
el.cpnd3 = {prop: 'cpnd3'};
el.cpnd4 = 'cpnd4';
el.cpnd5 = 'cpnd5';
assert.equal(el.$.boundChild.getAttribute('compoundAttr2'), 'literal1 cpnd1 literal2 cpnd2cpnd3 literal3 literalcpnd5cpnd4 literal4');
el.cpnd1 = null;
el.cpnd2 = undefined;
el.cpnd3 = {};
el.cpnd4 = '';
el.cpnd5 = '';
assert.equal(el.$.boundChild.getAttribute('compoundAttr2'), 'literal1 literal2 literal3 literal literal4');
});

test('compound adjacent textNode bindings', function() {
var el = document.createElement('x-basic');
assert.equal(el.$.compound1.textContent, '');
el.cpnd2 = 'cpnd2';
assert.equal(el.$.compound1.textContent, 'cpnd2');
el.cpnd1 = 'cpnd1';
el.cpnd3 = {prop: 'cpnd3'};
assert.equal(el.$.compound1.textContent, 'cpnd1cpnd2cpnd3');
el.cpnd4 = 'cpnd4';
assert.equal(el.$.compound1.textContent, 'cpnd1cpnd2cpnd3');
el.cpnd5 = 'cpnd5';
assert.equal(el.$.compound1.textContent, 'cpnd1cpnd2cpnd3literalcpnd5cpnd4');
});

test('compound textNode bindings with literals', function() {
var el = document.createElement('x-basic');
assert.equal(el.$.compound2.textContent.trim(), 'literal1 literal2 literal3 literal4');
el.cpnd1 = 'cpnd1';
el.cpnd2 = 'cpnd2';
el.cpnd3 = {prop: 'cpnd3'};
el.cpnd4 = 'cpnd4';
el.cpnd5 = 'cpnd5';
assert.equal(el.$.compound2.textContent.trim(), 'literal1 cpnd1 literal2 cpnd2cpnd3 literal3 literalcpnd5cpnd4 literal4');
el.cpnd1 = null;
el.cpnd2 = undefined;
el.cpnd3 = {};
el.cpnd4 = '';
el.cpnd5 = '';
assert.equal(el.$.compound2.textContent.trim(), 'literal1 literal2 literal3 literal literal4');
});
</script>

});

</script>

</body>
</html>

0 comments on commit c30ac10

Please sign in to comment.