Skip to content

Commit

Permalink
Ensure className bindings work correctly when ShadyDOM.noPatch is…
Browse files Browse the repository at this point in the history
… used.

Puts `className` on `Polymer.dom` and ensures any sets to `className` in the binding system, go through that wrapper.

Note, depends on webcomponents/shadydom#326.
  • Loading branch information
Steven Orvell committed Apr 2, 2019
1 parent b7c73bd commit eb2385a
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 2 deletions.
2 changes: 1 addition & 1 deletion lib/legacy/polymer.dom.js
Expand Up @@ -441,7 +441,7 @@ if (window['ShadyDOM'] && window['ShadyDOM']['inUse'] && window['ShadyDOM']['noP
]);

forwardProperties(DomApiNative.prototype, [
'textContent', 'innerHTML'
'textContent', 'innerHTML', 'className'
]);
}

Expand Down
8 changes: 8 additions & 0 deletions lib/mixins/property-effects.js
Expand Up @@ -727,6 +727,10 @@ function setupCompoundStorage(node, binding) {
storage[target] = literals;
// Configure properties with their literal parts
if (binding.literal && binding.kind == 'property') {
// Note, className needs style scoping so this needs wrapping.
if (target === 'className') {
node = wrap(node);
}
node[target] = binding.literal;
}
}
Expand Down Expand Up @@ -1407,6 +1411,10 @@ export const PropertyEffects = dedupingMixin(superClass => {
// implement a whitelist of tag & property values that should never
// be reset (e.g. <input>.value && <select>.value)
if (value !== node[prop] || typeof value == 'object') {
// Note, className needs style scoping so this needs wrapping.
if (prop === 'className') {
node = wrap(node);
}
node[prop] = value;
}
}
Expand Down
62 changes: 62 additions & 0 deletions test/unit/polymer-dom-nopatch.html
Expand Up @@ -72,6 +72,37 @@
</script>
</dom-module>

<dom-module id="x-class-bindings">
<template>
<style>
.a {
border: 2px solid orange;
}

.aa {
border: 12px solid red;
}

.b {
padding: 4px;
}
</style>
<div>
<div id="class" class$="[[clazz]] b">class</div>
<div id="className" class-name="[[clazz]] b">class</div>
</div>
</template>
<script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
properties: {
clazz: {type: String}
},
is: 'x-class-bindings'
});
</script>
</dom-module>

<test-fixture id="scoped">
<template>
<x-event-scoped></x-event-scoped>
Expand Down Expand Up @@ -493,6 +524,37 @@
assert.equal(el.className, 'foo');
});

test('className', function() {
dom(el).className = 'foo';
assert.isTrue(el.classList.contains('foo'));
});

test('class bindings work and remained scoped', function() {
const el = document.createElement('x-class-bindings');
document.body.appendChild(el);
assert.equal(getComputedStyle(el.$.class)['border-top-width'], '0px');
assert.equal(getComputedStyle(el.$.class)['padding-top'], '4px');
assert.isTrue(el.$.class.classList.contains('style-scope'));
assert.equal(getComputedStyle(el.$.className)['border-top-width'], '0px');
assert.equal(getComputedStyle(el.$.className)['padding-top'], '4px');
assert.isTrue(el.$.className.classList.contains('style-scope'));
el.clazz = 'a';
assert.equal(getComputedStyle(el.$.class)['border-top-width'], '2px');
assert.equal(getComputedStyle(el.$.class)['padding-top'], '4px');
assert.isTrue(el.$.class.classList.contains('style-scope'));
assert.equal(getComputedStyle(el.$.className)['border-top-width'], '2px');
assert.equal(getComputedStyle(el.$.className)['padding-top'], '4px');
assert.isTrue(el.$.className.classList.contains('style-scope'));
el.clazz = 'aa';
assert.equal(getComputedStyle(el.$.class)['border-top-width'], '12px');
assert.equal(getComputedStyle(el.$.class)['padding-top'], '4px');
assert.isTrue(el.$.class.classList.contains('style-scope'));
assert.equal(getComputedStyle(el.$.className)['border-top-width'], '12px');
assert.equal(getComputedStyle(el.$.className)['padding-top'], '4px');
assert.isTrue(el.$.className.classList.contains('style-scope'));
document.body.removeChild(el);
})

});
</script>

Expand Down
58 changes: 57 additions & 1 deletion test/unit/polymer-dom.html
Expand Up @@ -67,7 +67,38 @@
is: 'x-focusable-in-shadow'
});
</script>
</dom-module>
</dom-module>

<dom-module id="x-class-bindings">
<template>
<style>
.a {
border: 2px solid orange;
}

.aa {
border: 12px solid red;
}

.b {
padding: 4px;
}
</style>
<div>
<div id="class" class$="[[clazz]] b">class</div>
<div id="className" class-name="[[clazz]] b">class</div>
</div>
</template>
<script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
properties: {
clazz: {type: String}
},
is: 'x-class-bindings'
});
</script>
</dom-module>

<test-fixture id="scoped">
<template>
Expand Down Expand Up @@ -480,6 +511,31 @@
assert.equal(el.className, 'foo');
});

test('className', function() {
dom(el).className = 'foo';
assert.isTrue(el.classList.contains('foo'));
});

test('class bindings', function() {
const el = document.createElement('x-class-bindings');
document.body.appendChild(el);
assert.equal(getComputedStyle(el.$.class)['border-top-width'], '0px');
assert.equal(getComputedStyle(el.$.class)['padding-top'], '4px');
assert.equal(getComputedStyle(el.$.className)['border-top-width'], '0px');
assert.equal(getComputedStyle(el.$.className)['padding-top'], '4px');
el.clazz = 'a';
assert.equal(getComputedStyle(el.$.class)['border-top-width'], '2px');
assert.equal(getComputedStyle(el.$.class)['padding-top'], '4px');
assert.equal(getComputedStyle(el.$.className)['border-top-width'], '2px');
assert.equal(getComputedStyle(el.$.className)['padding-top'], '4px');
el.clazz = 'aa';
assert.equal(getComputedStyle(el.$.class)['border-top-width'], '12px');
assert.equal(getComputedStyle(el.$.class)['padding-top'], '4px');
assert.equal(getComputedStyle(el.$.className)['border-top-width'], '12px');
assert.equal(getComputedStyle(el.$.className)['padding-top'], '4px');
document.body.removeChild(el);
})

});
</script>

Expand Down

0 comments on commit eb2385a

Please sign in to comment.