Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 2.x hybrid affordances for stamping template content. Fixes #4536 #4537

Merged
merged 9 commits into from
Apr 17, 2017
12 changes: 10 additions & 2 deletions src/lib/template/dom-bind.html
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,16 @@
},

_insertChildren: function() {
var parentDom = Polymer.dom(Polymer.dom(this).parentNode);
parentDom.insertBefore(this.root, this);
var refNode;
var parentNode = Polymer.dom(this).parentNode;
// Affordance for 2.x hybrid mode
if (parentNode.localName == this.is) {
refNode = parentNode;
parentNode = Polymer.dom(parentNode).parentNode;
} else {
refNode = this;
}
Polymer.dom(parentNode).insertBefore(this.root, refNode);
},

_removeChildren: function() {
Expand Down
25 changes: 18 additions & 7 deletions src/lib/template/dom-if.html
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,14 @@
},

detached: function() {
if (!this.parentNode ||
(this.parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE &&
var parentNode = this.parentNode;
if (parentNode && parentNode.localName == this.is) {
parentNode = Polymer.dom(parentNode).parentNode;
}
if (!parentNode ||
(parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE &&
(!Polymer.Settings.hasShadow ||
!(this.parentNode instanceof ShadowRoot)))) {
!(parentNode instanceof ShadowRoot)))) {
this._teardownInstance();
}
},
Expand Down Expand Up @@ -131,22 +135,29 @@
},

_ensureInstance: function() {
var refNode;
var parentNode = Polymer.dom(this).parentNode;
// Affordance for 2.x hybrid mode
if (parentNode && parentNode.localName == this.is) {
refNode = parentNode;
parentNode = Polymer.dom(parentNode).parentNode;
} else {
refNode = this;
}
// Guard against element being detached while render was queued
if (parentNode) {
var parent = Polymer.dom(parentNode);
if (!this._instance) {
this._instance = this.stamp();
var root = this._instance.root;
parent.insertBefore(root, this);
Polymer.dom(parentNode).insertBefore(root, refNode);
} else {
var c$ = this._instance._children;
if (c$ && c$.length) {
// Detect case where dom-if was re-attached in new position
var lastChild = Polymer.dom(this).previousSibling;
var lastChild = Polymer.dom(refNode).previousSibling;
if (lastChild !== c$[c$.length-1]) {
for (var i=0, n; (i<c$.length) && (n=c$[i]); i++) {
parent.insertBefore(n, this);
Polymer.dom(parentNode).insertBefore(n, refNode);
}
}
}
Expand Down
24 changes: 20 additions & 4 deletions src/lib/template/dom-repeat.html
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,18 @@
// only perform attachment if the element was previously detached.
if (this.__isDetached) {
this.__isDetached = false;
var parent = Polymer.dom(Polymer.dom(this).parentNode);
var refNode;
var parentNode = Polymer.dom(this).parentNode;
// Affordance for 2.x hybrid mode
if (parentNode.localName == this.is) {
refNode = parentNode;
parentNode = Polymer.dom(parentNode).parentNode;
} else {
refNode = this;
}
var parent = Polymer.dom(parentNode);
for (var i=0; i<this._instances.length; i++) {
this._attachInstance(i, parent);
this._attachInstance(i, parent, refNode);
}
}
},
Expand Down Expand Up @@ -666,10 +675,10 @@
}
},

_attachInstance: function(idx, parent) {
_attachInstance: function(idx, parent, refNode) {
var inst = this._instances[idx];
if (!inst.isPlaceholder) {
parent.insertBefore(inst.root, this);
parent.insertBefore(inst.root, refNode);
}
},

Expand Down Expand Up @@ -710,6 +719,13 @@
var beforeRow = this._instances[idx + 1];
var beforeNode = beforeRow && !beforeRow.isPlaceholder ? beforeRow._children[0] : this;
var parentNode = Polymer.dom(this).parentNode;
// Affordance for 2.x hybrid mode
if (parentNode.localName == this.is) {
if (beforeNode == this) {
beforeNode = parentNode;
}
parentNode = Polymer.dom(parentNode).parentNode;
}
Polymer.dom(parentNode).insertBefore(inst.root, beforeNode);
this._instances[idx] = inst;
return inst;
Expand Down
37 changes: 35 additions & 2 deletions test/unit/dom-bind.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</template>

<script>
/* global earlyDomBind earlyBoundChild decEl1 decEl2 decDomBind z container needsHost*/
/* global earlyDomBind earlyBoundChild decEl1 decEl2 decDomBind z container needsHost hybridDomBind hybridEl1 hybridEl2*/
earlyDomBind.value = 'hi!';
</script>

Expand All @@ -42,6 +42,13 @@
<x-needs-host id="needsHost"></x-needs-host>
</template>

<dom-bind>
<template is="dom-bind" id="hybridDomBind">
<x-basic value="{{value}}" id="hybridEl1"></x-basic>
<x-basic value="{{value}}" id="hybridEl2"></x-basic>
</template>
</dom-bind>

<script>

suite('dom-bind touched before upgrade', function() {
Expand Down Expand Up @@ -235,7 +242,7 @@
Polymer.Settings.suppressTemplateNotifications ? 0 : 1);
done();
});
});
});

test('re-enable dom-change', function(done) {
if (Polymer.Settings.suppressTemplateNotifications) {
Expand All @@ -255,6 +262,32 @@

});

suite('hybrid dom-bind', function() {

var domBind;
var el1;
var el2;

setup(function() {
domBind = hybridDomBind;
el1 = hybridEl1;
el2 = hybridEl2;
});

test('value binds top-down', function() {
domBind.value = 'foo';
assert.equal(el1.value, 'foo');
assert.equal(el2.value, 'foo');
});

test('parent is parent of <dom-bind>', function() {
domBind.value = 'foo';
assert.equal(el1.parentNode, document.body);
assert.equal(el2.parentNode, document.body);
});

});

</script>

<link rel="import" href="dom-bind-elements2.html">
Expand Down
57 changes: 50 additions & 7 deletions test/unit/dom-if.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,51 @@
<template is="dom-if" if id="toBeRemoved"><div id="shouldBeRemoved"></div></template>
</div>

<!-- 2.x hybrid test -->
<dom-if id="hybridDomIfWrapper">
<template is="dom-if" id="hybridDomIf" if restamp>
<div hybrid-stamped>[[prop]]</div>
</template>
</dom-if>

<script>
/* global configured individual unconfigured1 unconfigured2 inDocumentContainer inDocumentIf structuredContainer structuredDomIf structuredDomBind outerContainer innerContainer shouldBeRemoved toBeRemoved removalContainer*/
/* global configured individual unconfigured1 unconfigured2 inDocumentContainer inDocumentIf structuredContainer structuredDomIf structuredDomBind outerContainer innerContainer shouldBeRemoved toBeRemoved removalContainer hybridDomIf hybridDomIfWrapper*/

suite('hybrid dom-if', function() {

test('parent is parent of <dom-if>', function() {
var stamped = [].slice.call(document.querySelectorAll('[hybrid-stamped]'));
assert.equal(stamped.length, 1);
assert.equal(stamped[0].parentNode, document.body);
});

test('remove & re-add works correctly', function(done) {
var wrapper = hybridDomIfWrapper;
var domIf = hybridDomIf;
Polymer.dom(document.body).removeChild(wrapper);
CustomElements.takeRecords();
domIf.render();
var stamped = [].slice.call(document.querySelectorAll('[hybrid-stamped]'));
assert.equal(stamped.length, 0);
Polymer.dom(removalContainer).appendChild(wrapper);
CustomElements.takeRecords();
setTimeout(function() {
stamped = [].slice.call(document.querySelectorAll('[hybrid-stamped]'));
assert.equal(stamped.length, 1);
assert.equal(stamped[0].parentNode, removalContainer);
done();
});
});

test('children removed correctly', function() {
hybridDomIf.if = false;
hybridDomIf.render();
var stamped = [].slice.call(document.querySelectorAll('[hybrid-stamped]'));
assert.equal(stamped.length, 0);
});

});

suite('nested pre-configured dom-if', function() {

test('parent scope binding', function() {
Expand Down Expand Up @@ -337,7 +380,7 @@
var stamped = Polymer.dom(unconfigured1.root).querySelectorAll('*:not(template):not(span)');
assert.equal(stamped.length, 3, 'total stamped count incorrect');
stamped[0].prop = 'outer';
assert.equal(unconfigured1.domUpdateHandlerCount,
assert.equal(unconfigured1.domUpdateHandlerCount,
Polymer.Settings.suppressTemplateNotifications ? 0 : 1);
});

Expand All @@ -352,7 +395,7 @@
stamped.forEach(function(n) {
assert.equal(getComputedStyle(n).display, 'none', 'node was not hidden but should have been');
});
assert.equal(unconfigured1.domUpdateHandlerCount,
assert.equal(unconfigured1.domUpdateHandlerCount,
Polymer.Settings.suppressTemplateNotifications ? 0 : 1);
});

Expand All @@ -368,7 +411,7 @@
stamped.forEach(function(n) {
assert.equal(getComputedStyle(n).display, 'inline', 'node was hidden but should not have been');
});
assert.equal(unconfigured1.domUpdateHandlerCount,
assert.equal(unconfigured1.domUpdateHandlerCount,
Polymer.Settings.suppressTemplateNotifications ? 0 : 1);
});

Expand All @@ -380,10 +423,10 @@
CustomElements.takeRecords();
CustomElements.takeRecords();
var stamped = Polymer.dom(unconfigured1.root).querySelectorAll('*:not(template)');
assert.equal(unconfigured1.domUpdateHandlerCount,
assert.equal(unconfigured1.domUpdateHandlerCount,
Polymer.Settings.suppressTemplateNotifications ? 0 : 1);
assert.equal(stamped.length, 0, 'total stamped count incorrect');
assert.equal(unconfigured1.domUpdateHandlerCount,
assert.equal(unconfigured1.domUpdateHandlerCount,
Polymer.Settings.suppressTemplateNotifications ? 0 : 1);
});

Expand All @@ -398,7 +441,7 @@
var stamped = Polymer.dom(unconfigured1.root).querySelectorAll('*:not(template):not(span)');
assert.equal(stamped.length, 3, 'total stamped count incorrect');
stamped[0].prop = 'outer';
assert.equal(unconfigured1.domUpdateHandlerCount,
assert.equal(unconfigured1.domUpdateHandlerCount,
Polymer.Settings.suppressTemplateNotifications ? 0 : 1);
});

Expand Down
Loading