Skip to content

Commit

Permalink
Adds Polymer.DisableUpgradeMixin
Browse files Browse the repository at this point in the history
Fixes #4909. Elements using this mixin will not "enable" themselves when they have a `disable-upgrade` attribute. This mirrors a feature of Polymer 1.x but is now opt-in.
  • Loading branch information
Steven Orvell committed Dec 15, 2017
1 parent 84abed1 commit 62ce314
Show file tree
Hide file tree
Showing 4 changed files with 316 additions and 0 deletions.
87 changes: 87 additions & 0 deletions lib/mixins/disable-upgrade-mixin.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<!--
@license
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<script>
(function() {

const DISABLED_ATTR = 'disable-upgrade';

/**
* Element class mixin that allows the element to boot up in a non-enabled
* state when the `disable-upgrade` attribute is present. This mixin is
* designed to be used with element classes like Polymer.Element that perform
* initial startup work when they are first connected. When the
* `disable-upgrade` attribute is removed, if the element is connected, it
* boots up and "enables" as it otherwise would; if it is not connected, the
* element boots up when it is next connected.
*
* Using `disable-upgrade` with Polymer.Element prevents any data propagation
* to the element, any element DOM from stamping, or any work done in
* connected/disconnctedCallback from occuring, but it does not prevent work
* done in the element constructor.
*
* Note, this mixin must be applied on top of any element class that
* itself implements a `connectedCallback` so that it can control the work
* done in `connectedCallback`. For example,
*
* MyClass = Polymer.DisableUpgradeMixin(class extends BaseClass {...});
*
* @mixinFunction
* @polymer
* @memberof Polymer
*/
Polymer.DisableUpgradeMixin = Polymer.dedupingMixin((base) => {

return class DisableUpgradeClass extends base {

static get observedAttributes() {
return super.observedAttributes.concat(DISABLED_ATTR);
}

attributeChangedCallback(name, old, value) {
if (name == DISABLED_ATTR) {
if (!this.__dataEnabled && value == null && this.isConnected) {
super.connectedCallback();
}
} else {
super.attributeChangedCallback(name, old, value);
}
}

__shouldEnable() {
return this.__dataEnabled || !this.hasAttribute(DISABLED_ATTR);
}

// prevent user code in connected from running
connectedCallback() {
if (this.__shouldEnable()) {
super.connectedCallback();
}
}

// prevent element from turning on properties
_enableProperties() {
if (this.__shouldEnable()) {
super._enableProperties();
}
}

// only go if "enabled"
disconnectedCallback() {
if (this.__dataEnabled) {
super.disconnectedCallback();
}
}

}
});

})();

</script>
1 change: 1 addition & 0 deletions test/runner.html
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
'unit/mixin-behaviors.html',
'unit/render-status.html',
'unit/dir.html',
'unit/disable-upgrade.html',
'unit/shady-unscoped-style.html',
'unit/html-tag.html'
// 'unit/multi-style.html'
Expand Down
101 changes: 101 additions & 0 deletions test/smoke/disable-upgrade.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<!doctype html>
<html>
<head>
<link rel="import" href="../../polymer.html">
<link rel="import" href="../../lib/mixins/disable-upgrade-mixin.html">
</head>
<body>
<script>
(function() {
const ogDefine = window.customElements.ogDefine = window.customElements.define;
window.customElements.defineWithDisabled = function(name, constructor) {
return ogDefine.call(customElements, name,
Polymer.DisableUpgradeMixin(constructor));
}
window.customElements.define = window.customElements.defineWithDisabled;
})();

</script>

<dom-module id="x-disabled">

<template>
<style>
:host {
display: block;
}

h2 {
letter-spacing: 1em;
}
</style>
<h2>[[prop]]</h2>
</template>

<script>
class Disabled extends Polymer.Element {
static get is() { return 'x-disabled'; }
static get properties() {
return {
prop: {
type: String
}
}
}
constructor() {
super();
this.prop = 'enabled!';
}
};
customElements.define(Disabled.is, Disabled);

</script>

</dom-module>

<dom-module id="my-element">

<template>
<style>
:host {
display: block;
}

button {
display: block;
}
</style>
<h3>x-disabled without disable-upgrade</h3>
<x-disabled>Disabled</x-disabled>
<h3>x-disabled with disable-upgrade</h3>
<x-disabled id="disabled" disable-upgrade>Disabled</x-disabled>
<h3>x-disabled with disable-upgrade</h3>
<x-disabled disable-upgrade$="[[upgradeDisabled]]">Disabled</x-disabled>
<button on-click="_enable">Enable</button>
</template>

<script>


class MyElement extends Polymer.Element {
static get is() { return 'my-element'; }
static get properties() {
return {
upgradeDisabled: {value: true}
}
}
_enable() {
this.$.disabled.removeAttribute('disable-upgrade');
this.upgradeDisabled = false;
}
}
customElements.define(MyElement.is, MyElement);

</script>

</dom-module>

<my-element></my-element>

</body>
</html>
127 changes: 127 additions & 0 deletions test/unit/disable-upgrade.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<!doctype html>
<!--
@license
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html dir="rtl">
<head>
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
<script src="../../../web-component-tester/browser.js"></script>
<link rel="import" href="../../polymer.html">
<link rel="import" href="../../lib/mixins/disable-upgrade-mixin.html">
</head>
<body>

<dom-module id="x-disabled">
<template>
<style>
:host {
display: block;
}

h2 {
letter-spacing: 1em;
}
</style>
<h2 id="element">[[prop]]</h2>
</template>

<script>
const Disabled = Polymer.DisableUpgradeMixin(class extends Polymer.Element {
static get is() { return 'x-disabled'; }
static get properties() {
return {
prop: {
type: String
}
}
}
constructor() {
super();
this.prop = 'enabled!';
}

ready() {
super.ready();
this.enabled = true;
}
});
customElements.define(Disabled.is, Disabled);

</script>

</dom-module>

<dom-module id="my-element">

<template>
<x-disabled id="enabledEl">Disabled</x-disabled>
<x-disabled id="disabledEl" disable-upgrade>Disabled</x-disabled>
<x-disabled id="disabledBoundEl" disable-upgrade$="[[upgradeDisabled]]">Disabled</x-disabled>
</template>

<script>
class MyElement extends Polymer.Element {
static get is() { return 'my-element'; }
static get properties() {
return {
upgradeDisabled: {value: true}
}
}
enable() {
this.$.disabledEl.removeAttribute('disable-upgrade');
this.upgradeDisabled = false;
}
}
customElements.define(MyElement.is, MyElement);

</script>

</dom-module>

<script>
suite('disable-upgrade', function() {
let el;

setup(() => {
el = document.createElement('my-element');
document.body.appendChild(el);
});
teardown(function() {
document.body.removeChild(el);
});

test('elements upgrade as expected with and without `disable-upgrade`', function() {
assert.ok(el.$.enabledEl.enabled);
assert.ok(el.$.enabledEl.$.element);
assert.equal(el.$.enabledEl.$.element.textContent, 'enabled!');
assert.notOk(el.$.disabledEl.enabled);
assert.notOk(el.$.disabledEl.$);
assert.notOk(el.$.disabledBoundEl.enabled);
assert.notOk(el.$.disabledBoundEl.$);
});

test('elements upgrade when `disable-upgrade` removed', function() {
assert.notOk(el.$.disabledEl.enabled);
assert.notOk(el.$.disabledEl.$);
assert.notOk(el.$.disabledBoundEl.enabled);
assert.notOk(el.$.disabledBoundEl.$);
el.enable();
assert.ok(el.$.disabledEl.enabled);
assert.ok(el.$.disabledEl.$.element);
assert.equal(el.$.disabledEl.$.element.textContent, 'enabled!');
assert.ok(el.$.disabledBoundEl.enabled);
assert.ok(el.$.disabledBoundEl.$.element);
assert.equal(el.$.disabledBoundEl.$.element.textContent, 'enabled!');
});


});
</script>
</body>
</html>

0 comments on commit 62ce314

Please sign in to comment.