Skip to content

Commit 21bee7a

Browse files
authored
fix: Content set, Safari 14.1.1. / WebKitGTK 2.32.0 (#1650)
* fix: Update content set to workaround Safari 14.1.1, WebKitGTK 2.32.0 bug * fix: Update commented out line * fix: Correct commented out break * fix: Update changelog * fix: Revert unrelated linting updates * fix: Set resize observer on this * fix: Switch to onresize event; update container query * fix: Add debounce * fix: Remove commented out resize * fix: Rework building content * fix: Revert breakpoint change * fix: Build wrapper no longer used * fix: Update tests to use promises * fix: IE11 bug fix * fix: Updated baselines for IE11 * fix: Update readme * fix: Add IE11 note to docs
1 parent 5cba1f4 commit 21bee7a

File tree

8 files changed

+143
-246
lines changed

8 files changed

+143
-246
lines changed

CHANGELOG-1.x.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 1.9.1 (2021-05-27)
2+
3+
- [](https://github.com/patternfly/patternfly-elements/commit/) fix: pfe-content-set, Safari 14.1.1 / WebKitGTK 2.32.0 bug fix
4+
15
# 1.9.0 (2021-05-26)
26

37
- [cb12965](https://github.com/patternfly/patternfly-elements/commit/cb12965db958aaded5baf5ba8867532346d63f03) feat: pfe-progress-steps (new) (#1436)

elements/pfe-content-set/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11

2-
# PatternFly Content set Element
2+
# PatternFly Content set
33

44
## Overview
55

66
`pfe-content-set` is a combo component, which brings together the utilities of the accordion and tabs components. Effectively both of these components do the same job, which is to encapsulate chunks of information under headings for easier browsing. Hiding some information and allowing the user to toggle through the headings to show other bits of information.
77

88
Since tabs can pose a layout issue on mobile because of the lack of horizontal space, this component will first assess the width of the parent container. If the width of pfe-content-set is less than or equal to 700px, the component will render the content within the `<pfe-accordion>` component. If it is larger than this value, the content will be rendered within the `<pfe-tabs>` component.
99

10+
_Note:_ In IE11, the component will only render as accordions and never as tabs.
11+
1012
## Dependencies
1113

1214
Requires both the `pfe-accordion` and `pfe-tabs` components, as well as the base `pfelement`.

elements/pfe-content-set/docs/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ Content set brings together the utilities of the accordion and tabs components.
2020

2121
Since tabs can pose a layout issue on mobile because of the lack of horizontal space, this component will first assess the width of the parent container. If the width of pfe-content-set is less than or equal to 700px, the component will render the content within the `<pfe-accordion>` component. If it is larger than this value, the content will be rendered within the `<pfe-tabs>` component.
2222

23+
_Note:_ In IE11, the component will only render as accordions and never as tabs.
24+
2325
### Large screens
2426
On large screens the content will display as tabs.
2527

elements/pfe-content-set/src/pfe-content-set.js

Lines changed: 64 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -174,16 +174,16 @@ class PfeContentSet extends PFElement {
174174
*/
175175
get view() {
176176
if (!this._rendered) return;
177-
178-
return this.shadowRoot.querySelector(`#container > ${this.expectedTag}`);
177+
return this.shadowRoot.querySelector(this.expectedTag);
179178
}
180179

181180
/**
182181
* Getter: should this be rendered as a tabset based on the breakpoint size
183182
* @returns {boolean} Is this a tabset?
184183
*/
185184
get expectedTag() {
186-
return this.isTab ? PfeTabs.tag : PfeAccordion.tag;
185+
if (this.isIE11) return "pfe-accordion";
186+
else return this.isTab ? "pfe-tabs" : "pfe-accordion";
187187
}
188188

189189
/**
@@ -236,7 +236,6 @@ class PfeContentSet extends PFElement {
236236
this._resizeHandler = this._resizeHandler.bind(this);
237237

238238
this._build = this._build.bind(this);
239-
this._buildWrapper = this._buildWrapper.bind(this);
240239
this._buildSets = this._buildSets.bind(this);
241240

242241
this._isHeader = this._isHeader.bind(this);
@@ -252,26 +251,37 @@ class PfeContentSet extends PFElement {
252251
this._updateBreakpoint = this._updateBreakpoint.bind(this);
253252

254253
this._observer = new MutationObserver(this._mutationHandler);
255-
if (window.ResizeObserver) this._resizeObserver = new ResizeObserver(this._resizeHandler);
256254
}
257255

258256
connectedCallback() {
259257
super.connectedCallback();
260258

259+
// this.setAttribute("hidden", "");
260+
261261
// Validate that the light DOM data exists before building
262-
if (this.hasValidLightDOM) {
263-
this._build();
262+
if (this.hasValidLightDOM) this._build();
264263

265-
if (!this.isIE11 && window.ResizeObserver && this.parentElement) {
266-
this._resizeObserver.observe(this.parentElement);
267-
}
268-
} else if (!this.isIE11) this._observer.observe(this, CONTENT_MUTATION_CONFIG);
264+
if (!this.isIE11) {
265+
window.addEventListener("resize", () => {
266+
clearTimeout(this._resizeHandler._tId);
267+
this._resizeHandler._tId = setTimeout(this._resizeHandler, 100);
268+
});
269+
270+
this._observer.observe(this, CONTENT_MUTATION_CONFIG);
271+
}
269272
}
270273

271274
disconnectedCallback() {
272275
super.disconnectedCallback();
273-
this._observer.disconnect();
274-
if (window.ResizeObserver) this._resizeObserver.disconnect();
276+
277+
if (!this.isIE11) {
278+
this._observer.disconnect();
279+
280+
window.removeEventListener("resize", () => {
281+
clearTimeout(this._resizeHandler._tId);
282+
this._resizeHandler._tId = setTimeout(this._resizeHandler, 100);
283+
});
284+
}
275285
}
276286

277287
/**
@@ -448,67 +458,51 @@ class PfeContentSet extends PFElement {
448458
* Manage the building of the rendering component
449459
* Optionally accepts the input of new nodes added to the DOM
450460
*/
451-
_build(addedNodes) {
452-
// @TODO: Add back a promise here post-IE11
453-
let view = this.view;
454-
if (!view || view.tag !== this.expectedTag) {
455-
view = this._buildWrapper();
456-
}
457-
458-
// Disconnect the observer while we parse it
459-
this._observer.disconnect();
460-
461-
let tag = view.tag || view.tagName.toLowerCase();
462-
const template = tag === "pfe-tabs" ? PfeTabs.contentTemplate : PfeAccordion.contentTemplate;
463-
464-
let rawSets = null;
465-
if (addedNodes) rawSets = addedNodes;
466-
if (!rawSets && [...this.children].length) rawSets = this.children;
467-
468-
// Clear out the content of the host if we're using the full child list
469-
if (!addedNodes && rawSets) view.innerHTML = "";
461+
// @TODO: Add back a promise here post-IE11
462+
_build() {
463+
const addedNodes = this.children;
470464

471465
// If sets is not null, build them using the template
472-
if (rawSets) {
473-
let sets = this._buildSets(rawSets, template);
474-
if (sets) view.appendChild(sets);
475-
}
476-
477-
// @todo find out why we need this shim
478-
// Shadydom breaks if we use innerHTML to set the new content but Selenium will infinitely
479-
// loop in out tests if we use appendChild.
480-
if (window.ShadyDOM) this.shadowRoot.querySelector(`#container`).appendChild(view);
481-
else this.shadowRoot.querySelector(`#container`).innerHTML = view.outerHTML;
482-
483-
Promise.all([customElements.whenDefined(tag)]).then(() => {
484-
this.cascadeProperties();
485-
486-
this.resetContext();
487-
488-
// Attach the mutation observer
489-
if (!this.isIE11) this._observer.observe(this, CONTENT_MUTATION_CONFIG);
490-
491-
return;
492-
});
493-
}
494-
495-
/*
496-
* Note: be sure to disconnect the observer before running this
497-
*/
498-
_buildWrapper() {
499-
// If the upgraded component matches the tag name of the expected rendering component, return now;
500-
if (this.view) return this.view;
466+
if (addedNodes.length > 0) {
467+
Promise.all([customElements.whenDefined(this.expectedTag)]).then(() => {
468+
const template = this.expectedTag === "pfe-tabs" ? PfeTabs.contentTemplate : PfeAccordion.contentTemplate;
469+
const sets = this._buildSets(addedNodes, template);
470+
const container = this.shadowRoot.querySelector("#container");
471+
472+
if (sets && container) {
473+
if (!this.isIE11) {
474+
// Disconnect the observer while we parse it
475+
this._observer.disconnect();
476+
477+
// This does not work in IE11 for some reason
478+
container.innerHTML = sets.outerHTML;
479+
480+
// Context is irrelevant in IE11
481+
this.resetContext();
482+
} else {
483+
container.innerHTML = "";
484+
container.appendChild(sets);
485+
486+
// In IE11, we need to hide the light DOM headers (b/c they're copied into shadow DOM on accordion)
487+
[...this.querySelectorAll("[pfe-content-set--header]")].map(item => {
488+
item.style.display = "none";
489+
});
490+
}
501491

502-
// Create the rendering element
503-
let newEl = document.createElement(this.expectedTag);
504-
newEl.id = this.id || this.pfeId || this.randomId;
492+
this.cascadeProperties();
493+
this.removeAttribute("hidden");
505494

506-
// Return the new element so that the content can be injected
507-
return newEl;
495+
// Attach the mutation observer
496+
if (!this.isIE11) this._observer.observe(this, CONTENT_MUTATION_CONFIG);
497+
}
498+
});
499+
} else {
500+
this.setAttribute("hidden", "");
501+
}
508502
}
509503

510504
_buildSets(sets, template) {
511-
let fragment = document.createDocumentFragment();
505+
let tagElement = document.createElement(this.expectedTag);
512506

513507
for (let i = 0; i < sets.length; i = i + 2) {
514508
let header = sets[i];
@@ -544,13 +538,13 @@ class PfeContentSet extends PFElement {
544538
// Capture the ID from the region or the pfe-id if they exist
545539
if (region.id || region.getAttribute("pfe-id")) piece.id = region.id || region.getAttribute("pfe-id");
546540

547-
// Attach the template item to the fragment
548-
fragment.appendChild(piece);
541+
// Attach the template item to the element tag
542+
tagElement.appendChild(piece);
549543
});
550544
}
551545
}
552546

553-
return fragment;
547+
return tagElement;
554548
}
555549

556550
_copyToId(oldVal, newVal) {

elements/pfe-content-set/src/polyfills--pfe-content-set.js

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,3 @@ if (window.NodeList && !NodeList.prototype.forEach) {
88
}
99
};
1010
}
11-
12-
// @POLYFILL Object.prototype.assign()
13-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill
14-
if (typeof Object.assign !== "function") {
15-
// Must be writable: true, enumerable: false, configurable: true
16-
Object.defineProperty(Object, "assign", {
17-
value: function assign(target, varArgs) {
18-
// .length of function is 2
19-
"use strict";
20-
if (target === null || target === undefined) {
21-
throw new TypeError("Cannot convert undefined or null to object");
22-
}
23-
24-
var to = Object(target);
25-
26-
for (var index = 1; index < arguments.length; index++) {
27-
var nextSource = arguments[index];
28-
29-
if (nextSource !== null && nextSource !== undefined) {
30-
for (var nextKey in nextSource) {
31-
// Avoid bugs when hasOwnProperty is shadowed
32-
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
33-
to[nextKey] = nextSource[nextKey];
34-
}
35-
}
36-
}
37-
}
38-
return to;
39-
},
40-
writable: true,
41-
configurable: true
42-
});
43-
}

0 commit comments

Comments
 (0)