-
Notifications
You must be signed in to change notification settings - Fork 319
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
Remove session storage checks from accordion JavaScript #5044
Conversation
📋 StatsFile sizes
Modules
View stats and visualisations on the review app Action run for df11d0b |
JavaScript changes to npm packagediff --git a/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js b/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js
index 83477260f..754775151 100644
--- a/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js
+++ b/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js
@@ -1,44 +1,44 @@
const version = "development";
function normaliseString(e, t) {
- const s = e ? e.trim() : "";
- let n, i = null == t ? void 0 : t.type;
- switch (i || (["true", "false"].includes(s) && (i = "boolean"), s.length > 0 && isFinite(Number(s)) && (i = "number")), i) {
+ const n = e ? e.trim() : "";
+ let i, s = null == t ? void 0 : t.type;
+ switch (s || (["true", "false"].includes(n) && (s = "boolean"), n.length > 0 && isFinite(Number(n)) && (s = "number")), s) {
case "boolean":
- n = "true" === s;
+ i = "true" === n;
break;
case "number":
- n = Number(s);
+ i = Number(n);
break;
default:
- n = e
+ i = e
}
- return n
+ return i
}
function mergeConfigs(...e) {
const t = {};
- for (const s of e)
- for (const e of Object.keys(s)) {
- const n = t[e],
- i = s[e];
- isObject(n) && isObject(i) ? t[e] = mergeConfigs(n, i) : t[e] = i
+ for (const n of e)
+ for (const e of Object.keys(n)) {
+ const i = t[e],
+ s = n[e];
+ isObject(i) && isObject(s) ? t[e] = mergeConfigs(i, s) : t[e] = s
}
return t
}
-function extractConfigByNamespace(e, t, s) {
- const n = e.schema.properties[s];
- if ("object" !== (null == n ? void 0 : n.type)) return;
- const i = {
- [s]: {}
+function extractConfigByNamespace(e, t, n) {
+ const i = e.schema.properties[n];
+ if ("object" !== (null == i ? void 0 : i.type)) return;
+ const s = {
+ [n]: {}
};
for (const [o, r] of Object.entries(t)) {
- let e = i;
+ let e = s;
const t = o.split(".");
- for (const [n, i] of t.entries()) "object" == typeof e && (n < t.length - 1 ? (isObject(e[i]) || (e[i] = {}), e = e[i]) : o !== s && (e[i] = normaliseString(r)))
+ for (const [i, s] of t.entries()) "object" == typeof e && (i < t.length - 1 ? (isObject(e[s]) || (e[s] = {}), e = e[s]) : o !== n && (e[s] = normaliseString(r)))
}
- return i[s]
+ return s[n]
}
function getFragmentFromUrl(e) {
@@ -54,20 +54,20 @@ function getBreakpoint(e) {
}
function setFocus(e, t = {}) {
- var s;
- const n = e.getAttribute("tabindex");
+ var n;
+ const i = e.getAttribute("tabindex");
function onBlur() {
- var s;
- null == (s = t.onBlur) || s.call(e), n || e.removeAttribute("tabindex")
+ var n;
+ null == (n = t.onBlur) || n.call(e), i || e.removeAttribute("tabindex")
}
- n || e.setAttribute("tabindex", "-1"), e.addEventListener("focus", (function() {
+ i || e.setAttribute("tabindex", "-1"), e.addEventListener("focus", (function() {
e.addEventListener("blur", onBlur, {
once: !0
})
}), {
once: !0
- }), null == (s = t.onBeforeFocus) || s.call(e), e.focus()
+ }), null == (n = t.onBeforeFocus) || n.call(e), e.focus()
}
function isSupported(e = document.body) {
@@ -81,9 +81,9 @@ function isObject(e) {
}
function normaliseDataset(e, t) {
- const s = {};
- for (const [n, i] of Object.entries(e.schema.properties)) n in t && (s[n] = normaliseString(t[n], i)), "object" === (null == i ? void 0 : i.type) && (s[n] = extractConfigByNamespace(e, t, n));
- return s
+ const n = {};
+ for (const [i, s] of Object.entries(e.schema.properties)) i in t && (n[i] = normaliseString(t[i], s)), "object" === (null == s ? void 0 : s.type) && (n[i] = extractConfigByNamespace(e, t, i));
+ return n
}
class GOVUKFrontendError extends Error {
constructor(...e) {
@@ -106,12 +106,12 @@ class ElementError extends GOVUKFrontendError {
let t = "string" == typeof e ? e : "";
if ("object" == typeof e) {
const {
- componentName: s,
- identifier: n,
- element: i,
+ componentName: n,
+ identifier: i,
+ element: s,
expectedType: o
} = e;
- t = `${s}: ${n}`, t += i ? ` is not of type ${null!=o?o:"HTMLElement"}` : " not found"
+ t = `${n}: ${i}`, t += s ? ` is not of type ${null!=o?o:"HTMLElement"}` : " not found"
}
super(t), this.name = "ElementError"
}
@@ -126,31 +126,31 @@ class GOVUKFrontendComponent {
}
class I18n {
constructor(e = {}, t = {}) {
- var s;
- this.translations = void 0, this.locale = void 0, this.translations = e, this.locale = null != (s = t.locale) ? s : document.documentElement.lang || "en"
+ var n;
+ this.translations = void 0, this.locale = void 0, this.translations = e, this.locale = null != (n = t.locale) ? n : document.documentElement.lang || "en"
}
t(e, t) {
if (!e) throw new Error("i18n: lookup key missing");
- let s = this.translations[e];
- if ("number" == typeof(null == t ? void 0 : t.count) && "object" == typeof s) {
- const n = s[this.getPluralSuffix(e, t.count)];
- n && (s = n)
+ let n = this.translations[e];
+ if ("number" == typeof(null == t ? void 0 : t.count) && "object" == typeof n) {
+ const i = n[this.getPluralSuffix(e, t.count)];
+ i && (n = i)
}
- if ("string" == typeof s) {
- if (s.match(/%{(.\S+)}/)) {
+ if ("string" == typeof n) {
+ if (n.match(/%{(.\S+)}/)) {
if (!t) throw new Error("i18n: cannot replace placeholders in string if no option data provided");
- return this.replacePlaceholders(s, t)
+ return this.replacePlaceholders(n, t)
}
- return s
+ return n
}
return e
}
replacePlaceholders(e, t) {
- const s = Intl.NumberFormat.supportedLocalesOf(this.locale).length ? new Intl.NumberFormat(this.locale) : void 0;
- return e.replace(/%{(.\S+)}/g, (function(e, n) {
- if (Object.prototype.hasOwnProperty.call(t, n)) {
- const e = t[n];
- return !1 === e || "number" != typeof e && "string" != typeof e ? "" : "number" == typeof e ? s ? s.format(e) : `${e}` : e
+ const n = Intl.NumberFormat.supportedLocalesOf(this.locale).length ? new Intl.NumberFormat(this.locale) : void 0;
+ return e.replace(/%{(.\S+)}/g, (function(e, i) {
+ if (Object.prototype.hasOwnProperty.call(t, i)) {
+ const e = t[i];
+ return !1 === e || "number" != typeof e && "string" != typeof e ? "" : "number" == typeof e ? n ? n.format(e) : `${e}` : e
}
throw new Error(`i18n: no data found to replace ${e} placeholder in string`)
}))
@@ -160,11 +160,11 @@ class I18n {
}
getPluralSuffix(e, t) {
if (t = Number(t), !isFinite(t)) return "other";
- const s = this.translations[e],
- n = this.hasIntlPluralRulesSupport() ? new Intl.PluralRules(this.locale).select(t) : this.selectPluralFormUsingFallbackRules(t);
- if ("object" == typeof s) {
- if (n in s) return n;
- if ("other" in s) return console.warn(`i18n: Missing plural form ".${n}" for "${this.locale}" locale. Falling back to ".other".`), "other"
+ const n = this.translations[e],
+ i = this.hasIntlPluralRulesSupport() ? new Intl.PluralRules(this.locale).select(t) : this.selectPluralFormUsingFallbackRules(t);
+ if ("object" == typeof n) {
+ if (i in n) return i;
+ if ("other" in n) return console.warn(`i18n: Missing plural form ".${i}" for "${this.locale}" locale. Falling back to ".other".`), "other"
}
throw new Error(`i18n: Plural form ".other" is required for "${this.locale}" locale`)
}
@@ -176,8 +176,8 @@ class I18n {
getPluralRulesForLocale() {
const e = this.locale.split("-")[0];
for (const t in I18n.pluralRulesMap) {
- const s = I18n.pluralRulesMap[t];
- if (s.includes(this.locale) || s.includes(e)) return t
+ const n = I18n.pluralRulesMap[t];
+ if (n.includes(this.locale) || n.includes(e)) return t
}
}
}
@@ -199,27 +199,27 @@ I18n.pluralRulesMap = {
irish: e => 1 === e ? "one" : 2 === e ? "two" : e >= 3 && e <= 6 ? "few" : e >= 7 && e <= 10 ? "many" : "other",
russian(e) {
const t = e % 100,
- s = t % 10;
- return 1 === s && 11 !== t ? "one" : s >= 2 && s <= 4 && !(t >= 12 && t <= 14) ? "few" : 0 === s || s >= 5 && s <= 9 || t >= 11 && t <= 14 ? "many" : "other"
+ n = t % 10;
+ return 1 === n && 11 !== t ? "one" : n >= 2 && n <= 4 && !(t >= 12 && t <= 14) ? "few" : 0 === n || n >= 5 && n <= 9 || t >= 11 && t <= 14 ? "many" : "other"
},
scottish: e => 1 === e || 11 === e ? "one" : 2 === e || 12 === e ? "two" : e >= 3 && e <= 10 || e >= 13 && e <= 19 ? "few" : "other",
spanish: e => 1 === e ? "one" : e % 1e6 == 0 && 0 !== e ? "many" : "other",
welsh: e => 0 === e ? "zero" : 1 === e ? "one" : 2 === e ? "two" : 3 === e ? "few" : 6 === e ? "many" : "other"
};
class Accordion extends GOVUKFrontendComponent {
- constructor(t, s = {}) {
- if (super(), this.$module = void 0, this.config = void 0, this.i18n = void 0, this.controlsClass = "govuk-accordion__controls", this.showAllClass = "govuk-accordion__show-all", this.showAllTextClass = "govuk-accordion__show-all-text", this.sectionClass = "govuk-accordion__section", this.sectionExpandedClass = "govuk-accordion__section--expanded", this.sectionButtonClass = "govuk-accordion__section-button", this.sectionHeaderClass = "govuk-accordion__section-header", this.sectionHeadingClass = "govuk-accordion__section-heading", this.sectionHeadingDividerClass = "govuk-accordion__section-heading-divider", this.sectionHeadingTextClass = "govuk-accordion__section-heading-text", this.sectionHeadingTextFocusClass = "govuk-accordion__section-heading-text-focus", this.sectionShowHideToggleClass = "govuk-accordion__section-toggle", this.sectionShowHideToggleFocusClass = "govuk-accordion__section-toggle-focus", this.sectionShowHideTextClass = "govuk-accordion__section-toggle-text", this.upChevronIconClass = "govuk-accordion-nav__chevron", this.downChevronIconClass = "govuk-accordion-nav__chevron--down", this.sectionSummaryClass = "govuk-accordion__section-summary", this.sectionSummaryFocusClass = "govuk-accordion__section-summary-focus", this.sectionContentClass = "govuk-accordion__section-content", this.$sections = void 0, this.browserSupportsSessionStorage = !1, this.$showAllButton = null, this.$showAllIcon = null, this.$showAllText = null, !(t instanceof HTMLElement)) throw new ElementError({
+ constructor(e, t = {}) {
+ if (super(), this.$module = void 0, this.config = void 0, this.i18n = void 0, this.controlsClass = "govuk-accordion__controls", this.showAllClass = "govuk-accordion__show-all", this.showAllTextClass = "govuk-accordion__show-all-text", this.sectionClass = "govuk-accordion__section", this.sectionExpandedClass = "govuk-accordion__section--expanded", this.sectionButtonClass = "govuk-accordion__section-button", this.sectionHeaderClass = "govuk-accordion__section-header", this.sectionHeadingClass = "govuk-accordion__section-heading", this.sectionHeadingDividerClass = "govuk-accordion__section-heading-divider", this.sectionHeadingTextClass = "govuk-accordion__section-heading-text", this.sectionHeadingTextFocusClass = "govuk-accordion__section-heading-text-focus", this.sectionShowHideToggleClass = "govuk-accordion__section-toggle", this.sectionShowHideToggleFocusClass = "govuk-accordion__section-toggle-focus", this.sectionShowHideTextClass = "govuk-accordion__section-toggle-text", this.upChevronIconClass = "govuk-accordion-nav__chevron", this.downChevronIconClass = "govuk-accordion-nav__chevron--down", this.sectionSummaryClass = "govuk-accordion__section-summary", this.sectionSummaryFocusClass = "govuk-accordion__section-summary-focus", this.sectionContentClass = "govuk-accordion__section-content", this.$sections = void 0, this.$showAllButton = null, this.$showAllIcon = null, this.$showAllText = null, !(e instanceof HTMLElement)) throw new ElementError({
componentName: "Accordion",
- element: t,
+ element: e,
identifier: "Root element (`$module`)"
});
- this.$module = t, this.config = mergeConfigs(Accordion.defaults, s, normaliseDataset(Accordion, t.dataset)), this.i18n = new I18n(this.config.i18n);
+ this.$module = e, this.config = mergeConfigs(Accordion.defaults, t, normaliseDataset(Accordion, e.dataset)), this.i18n = new I18n(this.config.i18n);
const n = this.$module.querySelectorAll(`.${this.sectionClass}`);
if (!n.length) throw new ElementError({
componentName: "Accordion",
identifier: `Sections (\`<div class="${this.sectionClass}">\`)`
});
- this.$sections = n, this.browserSupportsSessionStorage = e.checkForSessionStorage(), this.initControls(), this.initSectionHeaders(), this.updateShowAllButton(this.areAllSectionsOpen())
+ this.$sections = n, this.initControls(), this.initSectionHeaders(), this.updateShowAllButton(this.areAllSectionsOpen())
}
initControls() {
this.$showAllButton = document.createElement("button"), this.$showAllButton.setAttribute("type", "button"), this.$showAllButton.setAttribute("class", this.showAllClass), this.$showAllButton.setAttribute("aria-expanded", "false"), this.$showAllIcon = document.createElement("span"), this.$showAllIcon.classList.add(this.upChevronIconClass), this.$showAllButton.appendChild(this.$showAllIcon);
@@ -228,53 +228,53 @@ class Accordion extends GOVUKFrontendComponent {
}
initSectionHeaders() {
this.$sections.forEach(((e, t) => {
- const s = e.querySelector(`.${this.sectionHeaderClass}`);
- if (!s) throw new ElementError({
+ const n = e.querySelector(`.${this.sectionHeaderClass}`);
+ if (!n) throw new ElementError({
componentName: "Accordion",
identifier: `Section headers (\`<div class="${this.sectionHeaderClass}">\`)`
});
- this.constructHeaderMarkup(s, t), this.setExpanded(this.isExpanded(e), e), s.addEventListener("click", (() => this.onSectionToggle(e))), this.setInitialState(e)
+ this.constructHeaderMarkup(n, t), this.setExpanded(this.isExpanded(e), e), n.addEventListener("click", (() => this.onSectionToggle(e))), this.setInitialState(e)
}))
}
constructHeaderMarkup(e, t) {
- const s = e.querySelector(`.${this.sectionButtonClass}`),
- n = e.querySelector(`.${this.sectionHeadingClass}`),
- i = e.querySelector(`.${this.sectionSummaryClass}`);
- if (!n) throw new ElementError({
+ const n = e.querySelector(`.${this.sectionButtonClass}`),
+ i = e.querySelector(`.${this.sectionHeadingClass}`),
+ s = e.querySelector(`.${this.sectionSummaryClass}`);
+ if (!i) throw new ElementError({
componentName: "Accordion",
identifier: `Section heading (\`.${this.sectionHeadingClass}\`)`
});
- if (!s) throw new ElementError({
+ if (!n) throw new ElementError({
componentName: "Accordion",
identifier: `Section button placeholder (\`<span class="${this.sectionButtonClass}">\`)`
});
const o = document.createElement("button");
o.setAttribute("type", "button"), o.setAttribute("aria-controls", `${this.$module.id}-content-${t+1}`);
- for (const d of Array.from(s.attributes)) "id" !== d.name && o.setAttribute(d.name, d.value);
+ for (const d of Array.from(n.attributes)) "id" !== d.name && o.setAttribute(d.name, d.value);
const r = document.createElement("span");
- r.classList.add(this.sectionHeadingTextClass), r.id = s.id;
+ r.classList.add(this.sectionHeadingTextClass), r.id = n.id;
const a = document.createElement("span");
- a.classList.add(this.sectionHeadingTextFocusClass), r.appendChild(a), Array.from(s.childNodes).forEach((e => a.appendChild(e)));
+ a.classList.add(this.sectionHeadingTextFocusClass), r.appendChild(a), Array.from(n.childNodes).forEach((e => a.appendChild(e)));
const l = document.createElement("span");
l.classList.add(this.sectionShowHideToggleClass), l.setAttribute("data-nosnippet", "");
const c = document.createElement("span");
c.classList.add(this.sectionShowHideToggleFocusClass), l.appendChild(c);
const h = document.createElement("span"),
u = document.createElement("span");
- if (u.classList.add(this.upChevronIconClass), c.appendChild(u), h.classList.add(this.sectionShowHideTextClass), c.appendChild(h), o.appendChild(r), o.appendChild(this.getButtonPunctuationEl()), i) {
+ if (u.classList.add(this.upChevronIconClass), c.appendChild(u), h.classList.add(this.sectionShowHideTextClass), c.appendChild(h), o.appendChild(r), o.appendChild(this.getButtonPunctuationEl()), s) {
const e = document.createElement("span"),
t = document.createElement("span");
t.classList.add(this.sectionSummaryFocusClass), e.appendChild(t);
- for (const s of Array.from(i.attributes)) e.setAttribute(s.name, s.value);
- Array.from(i.childNodes).forEach((e => t.appendChild(e))), i.remove(), o.appendChild(e), o.appendChild(this.getButtonPunctuationEl())
+ for (const n of Array.from(s.attributes)) e.setAttribute(n.name, n.value);
+ Array.from(s.childNodes).forEach((e => t.appendChild(e))), s.remove(), o.appendChild(e), o.appendChild(this.getButtonPunctuationEl())
}
- o.appendChild(l), n.removeChild(s), n.appendChild(o)
+ o.appendChild(l), i.removeChild(n), i.appendChild(o)
}
onBeforeMatch(e) {
const t = e.target;
if (!(t instanceof Element)) return;
- const s = t.closest(`.${this.sectionClass}`);
- s && this.setExpanded(!0, s)
+ const n = t.closest(`.${this.sectionClass}`);
+ n && this.setExpanded(!0, n)
}
onSectionToggle(e) {
const t = !this.isExpanded(e);
@@ -287,24 +287,24 @@ class Accordion extends GOVUKFrontendComponent {
})), this.updateShowAllButton(e)
}
setExpanded(e, t) {
- const s = t.querySelector(`.${this.upChevronIconClass}`),
- n = t.querySelector(`.${this.sectionShowHideTextClass}`),
- i = t.querySelector(`.${this.sectionButtonClass}`),
+ const n = t.querySelector(`.${this.upChevronIconClass}`),
+ i = t.querySelector(`.${this.sectionShowHideTextClass}`),
+ s = t.querySelector(`.${this.sectionButtonClass}`),
o = t.querySelector(`.${this.sectionContentClass}`);
if (!o) throw new ElementError({
componentName: "Accordion",
identifier: `Section content (\`<div class="${this.sectionContentClass}">\`)`
});
- if (!s || !n || !i) return;
+ if (!n || !i || !s) return;
const r = e ? this.i18n.t("hideSection") : this.i18n.t("showSection");
- n.textContent = r, i.setAttribute("aria-expanded", `${e}`);
+ i.textContent = r, s.setAttribute("aria-expanded", `${e}`);
const a = [],
l = t.querySelector(`.${this.sectionHeadingTextClass}`);
l && a.push(`${l.textContent}`.trim());
const c = t.querySelector(`.${this.sectionSummaryClass}`);
c && a.push(`${c.textContent}`.trim());
const h = e ? this.i18n.t("hideSectionAriaLabel") : this.i18n.t("showSectionAriaLabel");
- a.push(h), i.setAttribute("aria-label", a.join(" , ")), e ? (o.removeAttribute("hidden"), t.classList.add(this.sectionExpandedClass), s.classList.remove(this.downChevronIconClass)) : (o.setAttribute("hidden", "until-found"), t.classList.remove(this.sectionExpandedClass), s.classList.add(this.downChevronIconClass)), this.updateShowAllButton(this.areAllSectionsOpen())
+ a.push(h), s.setAttribute("aria-label", a.join(" , ")), e ? (o.removeAttribute("hidden"), t.classList.add(this.sectionExpandedClass), n.classList.remove(this.downChevronIconClass)) : (o.setAttribute("hidden", "until-found"), t.classList.remove(this.sectionExpandedClass), n.classList.add(this.downChevronIconClass)), this.updateShowAllButton(this.areAllSectionsOpen())
}
isExpanded(e) {
return e.classList.contains(this.sectionExpandedClass)
@@ -315,24 +315,24 @@ class Accordion extends GOVUKFrontendComponent {
updateShowAllButton(e) {
this.$showAllButton && this.$showAllText && this.$showAllIcon && (this.$showAllButton.setAttribute("aria-expanded", e.toString()), this.$showAllText.textContent = e ? this.i18n.t("hideAllSections") : this.i18n.t("showAllSections"), this.$showAllIcon.classList.toggle(this.downChevronIconClass, !e))
}
+ getIdentifier(e) {
+ const t = e.querySelector(`.${this.sectionButtonClass}`);
+ return null == t ? void 0 : t.getAttribute("aria-controls")
+ }
storeState(e, t) {
- if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
- const s = e.querySelector(`.${this.sectionButtonClass}`);
- if (s) {
- const e = s.getAttribute("aria-controls");
- e && window.sessionStorage.setItem(e, t.toString())
- }
- }
+ if (!this.config.rememberExpanded) return;
+ const n = this.getIdentifier(e);
+ if (n) try {
+ window.sessionStorage.setItem(n, t.toString())
+ } catch (i) {}
}
setInitialState(e) {
- if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
- const t = e.querySelector(`.${this.sectionButtonClass}`);
- if (t) {
- const s = t.getAttribute("aria-controls"),
- n = s ? window.sessionStorage.getItem(s) : null;
- null !== n && this.setExpanded("true" === n, e)
- }
- }
+ if (!this.config.rememberExpanded) return;
+ const t = this.getIdentifier(e);
+ if (t) try {
+ const n = window.sessionStorage.getItem(t);
+ null !== n && this.setExpanded("true" === n, e)
+ } catch (n) {}
}
getButtonPunctuationEl() {
const e = document.createElement("span");
@@ -359,17 +359,6 @@ Accordion.moduleName = "govuk-accordion", Accordion.defaults = Object.freeze({
}
}
});
-const e = {
- checkForSessionStorage: function() {
- const e = "this is the test string";
- let t;
- try {
- return window.sessionStorage.setItem(e, e), t = window.sessionStorage.getItem(e) === e.toString(), window.sessionStorage.removeItem(e), t
- } catch (s) {
- return !1
- }
- }
-};
class Button extends GOVUKFrontendComponent {
constructor(e, t = {}) {
if (super(), this.$module = void 0, this.config = void 0, this.debounceFormSubmitTimer = null, !(e instanceof HTMLElement)) throw new ElementError({
@@ -391,8 +380,8 @@ class Button extends GOVUKFrontendComponent {
}
function closestAttributeValue(e, t) {
- const s = e.closest(`[${t}]`);
- return s ? s.getAttribute(t) : null
+ const n = e.closest(`[${t}]`);
+ return n ? n.getAttribute(t) : null
}
Button.moduleName = "govuk-button", Button.defaults = Object.freeze({
preventDoubleClick: !1
@@ -405,16 +394,16 @@ Button.moduleName = "govuk-button", Button.defaults = Object.freeze({
});
class CharacterCount extends GOVUKFrontendComponent {
constructor(e, t = {}) {
- var s, n;
+ var n, i;
if (super(), this.$module = void 0, this.$textarea = void 0, this.$visibleCountMessage = void 0, this.$screenReaderCountMessage = void 0, this.lastInputTimestamp = null, this.lastInputValue = "", this.valueChecker = null, this.config = void 0, this.i18n = void 0, this.maxLength = void 0, !(e instanceof HTMLElement)) throw new ElementError({
componentName: "Character count",
element: e,
identifier: "Root element (`$module`)"
});
- const i = e.querySelector(".govuk-js-character-count");
- if (!(i instanceof HTMLTextAreaElement || i instanceof HTMLInputElement)) throw new ElementError({
+ const s = e.querySelector(".govuk-js-character-count");
+ if (!(s instanceof HTMLTextAreaElement || s instanceof HTMLInputElement)) throw new ElementError({
componentName: "Character count",
- element: i,
+ element: s,
expectedType: "HTMLTextareaElement or HTMLInputElement",
identifier: "Form field (`.govuk-js-character-count`)"
});
@@ -425,24 +414,24 @@ class CharacterCount extends GOVUKFrontendComponent {
maxwords: void 0
}), this.config = mergeConfigs(CharacterCount.defaults, t, r, o);
const a = function(e, t) {
- const s = [];
- for (const [n, i] of Object.entries(e)) {
+ const n = [];
+ for (const [i, s] of Object.entries(e)) {
const e = [];
- if (Array.isArray(i)) {
+ if (Array.isArray(s)) {
for (const {
- required: s,
- errorMessage: n
+ required: n,
+ errorMessage: i
}
- of i) s.every((e => !!t[e])) || e.push(n);
- "anyOf" !== n || i.length - e.length >= 1 || s.push(...e)
+ of s) n.every((e => !!t[e])) || e.push(i);
+ "anyOf" !== i || s.length - e.length >= 1 || n.push(...e)
}
}
- return s
+ return n
}(CharacterCount.schema, this.config);
if (a[0]) throw new ConfigError(`Character count: ${a[0]}`);
this.i18n = new I18n(this.config.i18n, {
locale: closestAttributeValue(e, "lang")
- }), this.maxLength = null != (s = null != (n = this.config.maxwords) ? n : this.config.maxlength) ? s : 1 / 0, this.$module = e, this.$textarea = i;
+ }), this.maxLength = null != (n = null != (i = this.config.maxwords) ? i : this.config.maxlength) ? n : 1 / 0, this.$module = e, this.$textarea = s;
const l = `${this.$textarea.id}-info`,
c = document.getElementById(l);
if (!c) throw new ElementError({
@@ -499,8 +488,8 @@ class CharacterCount extends GOVUKFrontendComponent {
}
formatCountMessage(e, t) {
if (0 === e) return this.i18n.t(`${t}AtLimit`);
- const s = e < 0 ? "OverLimit" : "UnderLimit";
- return this.i18n.t(`${t}${s}`, {
+ const n = e < 0 ? "OverLimit" : "UnderLimit";
+ return this.i18n.t(`${t}${n}`, {
count: Math.abs(e)
})
}
@@ -587,10 +576,10 @@ class Checkboxes extends GOVUKFrontendComponent {
syncConditionalRevealWithInputState(e) {
const t = e.getAttribute("aria-controls");
if (!t) return;
- const s = document.getElementById(t);
- if (null != s && s.classList.contains("govuk-checkboxes__conditional")) {
+ const n = document.getElementById(t);
+ if (null != n && n.classList.contains("govuk-checkboxes__conditional")) {
const t = e.checked;
- e.setAttribute("aria-expanded", t.toString()), s.classList.toggle("govuk-checkboxes__conditional--hidden", !t)
+ e.setAttribute("aria-expanded", t.toString()), n.classList.toggle("govuk-checkboxes__conditional--hidden", !t)
}
}
unCheckAllInputsExcept(e) {
@@ -628,25 +617,25 @@ class ErrorSummary extends GOVUKFrontendComponent {
if (!(e instanceof HTMLAnchorElement)) return !1;
const t = getFragmentFromUrl(e.href);
if (!t) return !1;
- const s = document.getElementById(t);
- if (!s) return !1;
- const n = this.getAssociatedLegendOrLabel(s);
- return !!n && (n.scrollIntoView(), s.focus({
+ const n = document.getElementById(t);
+ if (!n) return !1;
+ const i = this.getAssociatedLegendOrLabel(n);
+ return !!i && (i.scrollIntoView(), n.focus({
preventScroll: !0
}), !0)
}
getAssociatedLegendOrLabel(e) {
var t;
- const s = e.closest("fieldset");
- if (s) {
- const t = s.getElementsByTagName("legend");
+ const n = e.closest("fieldset");
+ if (n) {
+ const t = n.getElementsByTagName("legend");
if (t.length) {
- const s = t[0];
- if (e instanceof HTMLInputElement && ("checkbox" === e.type || "radio" === e.type)) return s;
- const n = s.getBoundingClientRect().top,
- i = e.getBoundingClientRect();
- if (i.height && window.innerHeight) {
- if (i.top + i.height - n < window.innerHeight / 2) return s
+ const n = t[0];
+ if (e instanceof HTMLInputElement && ("checkbox" === e.type || "radio" === e.type)) return n;
+ const i = n.getBoundingClientRect().top,
+ s = e.getBoundingClientRect();
+ if (s.height && window.innerHeight) {
+ if (s.top + s.height - i < window.innerHeight / 2) return n
}
}
}
@@ -669,16 +658,16 @@ class ExitThisPage extends GOVUKFrontendComponent {
element: e,
identifier: "Root element (`$module`)"
});
- const s = e.querySelector(".govuk-exit-this-page__button");
- if (!(s instanceof HTMLAnchorElement)) throw new ElementError({
+ const n = e.querySelector(".govuk-exit-this-page__button");
+ if (!(n instanceof HTMLAnchorElement)) throw new ElementError({
componentName: "Exit this page",
- element: s,
+ element: n,
expectedType: "HTMLAnchorElement",
identifier: "Button (`.govuk-exit-this-page__button`)"
});
- this.config = mergeConfigs(ExitThisPage.defaults, t, normaliseDataset(ExitThisPage, e.dataset)), this.i18n = new I18n(this.config.i18n), this.$module = e, this.$button = s;
- const n = document.querySelector(".govuk-js-exit-this-page-skiplink");
- n instanceof HTMLAnchorElement && (this.$skiplinkButton = n), this.buildIndicator(), this.initUpdateSpan(), this.initButtonClickHandler(), "govukFrontendExitThisPageKeypress" in document.body.dataset || (document.addEventListener("keyup", this.handleKeypress.bind(this), !0), document.body.dataset.govukFrontendExitThisPageKeypress = "true"), window.addEventListener("pageshow", this.resetPage.bind(this))
+ this.config = mergeConfigs(ExitThisPage.defaults, t, normaliseDataset(ExitThisPage, e.dataset)), this.i18n = new I18n(this.config.i18n), this.$module = e, this.$button = n;
+ const i = document.querySelector(".govuk-js-exit-this-page-skiplink");
+ i instanceof HTMLAnchorElement && (this.$skiplinkButton = i), this.buildIndicator(), this.initUpdateSpan(), this.initButtonClickHandler(), "govukFrontendExitThisPageKeypress" in document.body.dataset || (document.addEventListener("keyup", this.handleKeypress.bind(this), !0), document.body.dataset.govukFrontendExitThisPageKeypress = "true"), window.addEventListener("pageshow", this.resetPage.bind(this))
}
initUpdateSpan() {
this.$updateSpan = document.createElement("span"), this.$updateSpan.setAttribute("role", "status"), this.$updateSpan.className = "govuk-visually-hidden", this.$module.appendChild(this.$updateSpan)
@@ -749,18 +738,18 @@ class Header extends GOVUKFrontendComponent {
this.$module = e;
const t = e.querySelector(".govuk-js-header-toggle");
if (!t) return this;
- const s = t.getAttribute("aria-controls");
- if (!s) throw new ElementError({
+ const n = t.getAttribute("aria-controls");
+ if (!n) throw new ElementError({
componentName: "Header",
identifier: 'Navigation button (`<button class="govuk-js-header-toggle">`) attribute (`aria-controls`)'
});
- const n = document.getElementById(s);
- if (!n) throw new ElementError({
+ const i = document.getElementById(n);
+ if (!i) throw new ElementError({
componentName: "Header",
- element: n,
- identifier: `Navigation (\`<ul id="${s}">\`)`
+ element: i,
+ identifier: `Navigation (\`<ul id="${n}">\`)`
});
- this.$menu = n, this.$menuButton = t, this.setupResponsiveChecks(), this.$menuButton.addEventListener("click", (() => this.handleMenuButtonClick()))
+ this.$menu = i, this.$menuButton = t, this.setupResponsiveChecks(), this.$menuButton.addEventListener("click", (() => this.handleMenuButtonClick()))
}
setupResponsiveChecks() {
const e = getBreakpoint("desktop");
@@ -804,27 +793,27 @@ class PasswordInput extends GOVUKFrontendComponent {
element: e,
identifier: "Root element (`$module`)"
});
- const s = e.querySelector(".govuk-js-password-input-input");
- if (!(s instanceof HTMLInputElement)) throw new ElementError({
+ const n = e.querySelector(".govuk-js-password-input-input");
+ if (!(n instanceof HTMLInputElement)) throw new ElementError({
componentName: "Password input",
- element: s,
+ element: n,
expectedType: "HTMLInputElement",
identifier: "Form field (`.govuk-js-password-input-input`)"
});
- if ("password" !== s.type) throw new ElementError("Password input: Form field (`.govuk-js-password-input-input`) must be of type `password`.");
- const n = e.querySelector(".govuk-js-password-input-toggle");
- if (!(n instanceof HTMLButtonElement)) throw new ElementError({
+ if ("password" !== n.type) throw new ElementError("Password input: Form field (`.govuk-js-password-input-input`) must be of type `password`.");
+ const i = e.querySelector(".govuk-js-password-input-toggle");
+ if (!(i instanceof HTMLButtonElement)) throw new ElementError({
componentName: "Password input",
- element: n,
+ element: i,
expectedType: "HTMLButtonElement",
identifier: "Button (`.govuk-js-password-input-toggle`)"
});
- if ("button" !== n.type) throw new ElementError("Password input: Button (`.govuk-js-password-input-toggle`) must be of type `button`.");
- this.$module = e, this.$input = s, this.$showHideButton = n, this.config = mergeConfigs(PasswordInput.defaults, t, normaliseDataset(PasswordInput, e.dataset)), this.i18n = new I18n(this.config.i18n, {
+ if ("button" !== i.type) throw new ElementError("Password input: Button (`.govuk-js-password-input-toggle`) must be of type `button`.");
+ this.$module = e, this.$input = n, this.$showHideButton = i, this.config = mergeConfigs(PasswordInput.defaults, t, normaliseDataset(PasswordInput, e.dataset)), this.i18n = new I18n(this.config.i18n, {
locale: closestAttributeValue(e, "lang")
}), this.$showHideButton.removeAttribute("hidden");
- const i = document.createElement("div");
- i.className = "govuk-password-input__sr-status govuk-visually-hidden", i.setAttribute("aria-live", "polite"), this.$screenReaderStatusMessage = i, this.$input.insertAdjacentElement("afterend", i), this.$showHideButton.addEventListener("click", this.toggle.bind(this)), this.$input.form && this.$input.form.addEventListener("submit", (() => this.hide())), window.addEventListener("pageshow", (e => {
+ const s = document.createElement("div");
+ s.className = "govuk-password-input__sr-status govuk-visually-hidden", s.setAttribute("aria-live", "polite"), this.$screenReaderStatusMessage = s, this.$input.insertAdjacentElement("afterend", s), this.$showHideButton.addEventListener("click", this.toggle.bind(this)), this.$input.form && this.$input.form.addEventListener("submit", (() => this.hide())), window.addEventListener("pageshow", (e => {
e.persisted && "password" !== this.$input.type && this.hide()
})), this.hide()
}
@@ -841,9 +830,9 @@ class PasswordInput extends GOVUKFrontendComponent {
if (e === this.$input.type) return;
this.$input.setAttribute("type", e);
const t = "password" === e,
- s = t ? "show" : "hide",
- n = t ? "passwordHidden" : "passwordShown";
- this.$showHideButton.innerText = this.i18n.t(`${s}Password`), this.$showHideButton.setAttribute("aria-label", this.i18n.t(`${s}PasswordAriaLabel`)), this.$screenReaderStatusMessage.innerText = this.i18n.t(`${n}Announcement`)
+ n = t ? "show" : "hide",
+ i = t ? "passwordHidden" : "passwordShown";
+ this.$showHideButton.innerText = this.i18n.t(`${n}Password`), this.$showHideButton.setAttribute("aria-label", this.i18n.t(`${n}PasswordAriaLabel`)), this.$screenReaderStatusMessage.innerText = this.i18n.t(`${i}Announcement`)
}
}
PasswordInput.moduleName = "govuk-password-input", PasswordInput.defaults = Object.freeze({
@@ -891,21 +880,21 @@ class Radios extends GOVUKFrontendComponent {
syncConditionalRevealWithInputState(e) {
const t = e.getAttribute("aria-controls");
if (!t) return;
- const s = document.getElementById(t);
- if (null != s && s.classList.contains("govuk-radios__conditional")) {
+ const n = document.getElementById(t);
+ if (null != n && n.classList.contains("govuk-radios__conditional")) {
const t = e.checked;
- e.setAttribute("aria-expanded", t.toString()), s.classList.toggle("govuk-radios__conditional--hidden", !t)
+ e.setAttribute("aria-expanded", t.toString()), n.classList.toggle("govuk-radios__conditional--hidden", !t)
}
}
handleClick(e) {
const t = e.target;
if (!(t instanceof HTMLInputElement) || "radio" !== t.type) return;
- const s = document.querySelectorAll('input[type="radio"][aria-controls]'),
- n = t.form,
- i = t.name;
- s.forEach((e => {
- const t = e.form === n;
- e.name === i && t && this.syncConditionalRevealWithInputState(e)
+ const n = document.querySelectorAll('input[type="radio"][aria-controls]'),
+ i = t.form,
+ s = t.name;
+ n.forEach((e => {
+ const t = e.form === i;
+ e.name === s && t && this.syncConditionalRevealWithInputState(e)
}))
}
}
@@ -920,17 +909,17 @@ class SkipLink extends GOVUKFrontendComponent {
identifier: "Root element (`$module`)"
});
this.$module = e;
- const s = this.$module.hash,
- n = null != (t = this.$module.getAttribute("href")) ? t : "";
- let i;
+ const n = this.$module.hash,
+ i = null != (t = this.$module.getAttribute("href")) ? t : "";
+ let s;
try {
- i = new window.URL(this.$module.href)
+ s = new window.URL(this.$module.href)
} catch (a) {
- throw new ElementError(`Skip link: Target link (\`href="${n}"\`) is invalid`)
+ throw new ElementError(`Skip link: Target link (\`href="${i}"\`) is invalid`)
}
- if (i.origin !== window.location.origin || i.pathname !== window.location.pathname) return;
- const o = getFragmentFromUrl(s);
- if (!o) throw new ElementError(`Skip link: Target link (\`href="${n}"\`) has no hash fragment`);
+ if (s.origin !== window.location.origin || s.pathname !== window.location.pathname) return;
+ const o = getFragmentFromUrl(n);
+ if (!o) throw new ElementError(`Skip link: Target link (\`href="${i}"\`) has no hash fragment`);
const r = document.getElementById(o);
if (!r) throw new ElementError({
componentName: "Skip link",
@@ -961,17 +950,17 @@ class Tabs extends GOVUKFrontendComponent {
identifier: 'Links (`<a class="govuk-tabs__tab">`)'
});
this.$module = e, this.$tabs = t, this.boundTabClick = this.onTabClick.bind(this), this.boundTabKeydown = this.onTabKeydown.bind(this), this.boundOnHashChange = this.onHashChange.bind(this);
- const s = this.$module.querySelector(".govuk-tabs__list"),
- n = this.$module.querySelectorAll("li.govuk-tabs__list-item");
- if (!s) throw new ElementError({
+ const n = this.$module.querySelector(".govuk-tabs__list"),
+ i = this.$module.querySelectorAll("li.govuk-tabs__list-item");
+ if (!n) throw new ElementError({
componentName: "Tabs",
identifier: 'List (`<ul class="govuk-tabs__list">`)'
});
- if (!n.length) throw new ElementError({
+ if (!i.length) throw new ElementError({
componentName: "Tabs",
identifier: 'List items (`<li class="govuk-tabs__list-item">`)'
});
- this.$tabList = s, this.$tabListItems = n, this.setupResponsiveChecks()
+ this.$tabList = n, this.$tabListItems = i, this.setupResponsiveChecks()
}
setupResponsiveChecks() {
const e = getBreakpoint("tablet");
@@ -1007,8 +996,8 @@ class Tabs extends GOVUKFrontendComponent {
t = this.getTab(e);
if (!t) return;
if (this.changingHash) return void(this.changingHash = !1);
- const s = this.getCurrentTab();
- s && (this.hideTab(s), this.showTab(t), t.focus())
+ const n = this.getCurrentTab();
+ n && (this.hideTab(n), this.showTab(t), t.focus())
}
hideTab(e) {
this.unhighlightTab(e), this.hidePanel(e)
@@ -1023,8 +1012,8 @@ class Tabs extends GOVUKFrontendComponent {
const t = getFragmentFromUrl(e.href);
if (!t) return;
e.setAttribute("id", `tab_${t}`), e.setAttribute("role", "tab"), e.setAttribute("aria-controls", t), e.setAttribute("aria-selected", "false"), e.setAttribute("tabindex", "-1");
- const s = this.getPanel(e);
- s && (s.setAttribute("role", "tabpanel"), s.setAttribute("aria-labelledby", e.id), s.classList.add(this.jsHiddenClass))
+ const n = this.getPanel(e);
+ n && (n.setAttribute("role", "tabpanel"), n.setAttribute("aria-labelledby", e.id), n.classList.add(this.jsHiddenClass))
}
unsetAttributes(e) {
e.removeAttribute("id"), e.removeAttribute("role"), e.removeAttribute("aria-controls"), e.removeAttribute("aria-selected"), e.removeAttribute("tabindex");
@@ -1033,14 +1022,14 @@ class Tabs extends GOVUKFrontendComponent {
}
onTabClick(e) {
const t = this.getCurrentTab(),
- s = e.currentTarget;
- t && s instanceof HTMLAnchorElement && (e.preventDefault(), this.hideTab(t), this.showTab(s), this.createHistoryEntry(s))
+ n = e.currentTarget;
+ t && n instanceof HTMLAnchorElement && (e.preventDefault(), this.hideTab(t), this.showTab(n), this.createHistoryEntry(n))
}
createHistoryEntry(e) {
const t = this.getPanel(e);
if (!t) return;
- const s = t.id;
- t.id = "", this.changingHash = !0, window.location.hash = s, t.id = s
+ const n = t.id;
+ t.id = "", this.changingHash = !0, window.location.hash = n, t.id = n
}
onTabKeydown(e) {
switch (e.key) {
@@ -1062,16 +1051,16 @@ class Tabs extends GOVUKFrontendComponent {
if (null == e || !e.parentElement) return;
const t = e.parentElement.nextElementSibling;
if (!t) return;
- const s = t.querySelector("a.govuk-tabs__tab");
- s && (this.hideTab(e), this.showTab(s), s.focus(), this.createHistoryEntry(s))
+ const n = t.querySelector("a.govuk-tabs__tab");
+ n && (this.hideTab(e), this.showTab(n), n.focus(), this.createHistoryEntry(n))
}
activatePreviousTab() {
const e = this.getCurrentTab();
if (null == e || !e.parentElement) return;
const t = e.parentElement.previousElementSibling;
if (!t) return;
- const s = t.querySelector("a.govuk-tabs__tab");
- s && (this.hideTab(e), this.showTab(s), s.focus(), this.createHistoryEntry(s))
+ const n = t.querySelector("a.govuk-tabs__tab");
+ n && (this.hideTab(e), this.showTab(n), n.focus(), this.createHistoryEntry(n))
}
getPanel(e) {
const t = getFragmentFromUrl(e.href);
@@ -1099,7 +1088,7 @@ class Tabs extends GOVUKFrontendComponent {
function initAll(e) {
var t;
if (e = void 0 !== e ? e : {}, !isSupported()) return void console.log(new SupportError);
- const s = [
+ const n = [
[Accordion, e.accordion],
[Button, e.button],
[CharacterCount, e.characterCount],
@@ -1113,19 +1102,19 @@ function initAll(e) {
[SkipLink],
[Tabs]
],
- n = null != (t = e.scope) ? t : document;
- s.forEach((([e, t]) => {
- createAll(e, t, n)
+ i = null != (t = e.scope) ? t : document;
+ n.forEach((([e, t]) => {
+ createAll(e, t, i)
}))
}
-function createAll(e, t, s = document) {
- const n = s.querySelectorAll(`[data-module="${e.moduleName}"]`);
- return Array.from(n).map((s => {
+function createAll(e, t, n = document) {
+ const i = n.querySelectorAll(`[data-module="${e.moduleName}"]`);
+ return Array.from(i).map((n => {
try {
- return "defaults" in e && void 0 !== t ? new e(s, t) : new e(s)
- } catch (n) {
- return console.log(n), null
+ return "defaults" in e && void 0 !== t ? new e(n, t) : new e(n)
+ } catch (i) {
+ return console.log(i), null
}
})).filter(Boolean)
}
Action run for df11d0b |
Other changes to npm packagediff --git a/packages/govuk-frontend/dist/govuk/all.bundle.js b/packages/govuk-frontend/dist/govuk/all.bundle.js
index 267a57bfc..fbc644fbf 100644
--- a/packages/govuk-frontend/dist/govuk/all.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/all.bundle.js
@@ -473,7 +473,6 @@
this.sectionSummaryFocusClass = 'govuk-accordion__section-summary-focus';
this.sectionContentClass = 'govuk-accordion__section-content';
this.$sections = void 0;
- this.browserSupportsSessionStorage = false;
this.$showAllButton = null;
this.$showAllIcon = null;
this.$showAllText = null;
@@ -495,7 +494,6 @@
});
}
this.$sections = $sections;
- this.browserSupportsSessionStorage = helper.checkForSessionStorage();
this.initControls();
this.initSectionHeaders();
this.updateShowAllButton(this.areAllSectionsOpen());
@@ -674,27 +672,44 @@
this.$showAllText.textContent = expanded ? this.i18n.t('hideAllSections') : this.i18n.t('showAllSections');
this.$showAllIcon.classList.toggle(this.downChevronIconClass, !expanded);
}
+
+ /**
+ * Get the identifier for a section
+ *
+ * We need a unique way of identifying each content in the Accordion.
+ * Since an `#id` should be unique and an `id` is required for `aria-`
+ * attributes `id` can be safely used.
+ *
+ * @param {Element} $section - Section element
+ * @returns {string | undefined | null} Identifier for section
+ */
+ getIdentifier($section) {
+ const $button = $section.querySelector(`.${this.sectionButtonClass}`);
+ return $button == null ? void 0 : $button.getAttribute('aria-controls');
+ }
storeState($section, isExpanded) {
- if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
- const $button = $section.querySelector(`.${this.sectionButtonClass}`);
- if ($button) {
- const contentId = $button.getAttribute('aria-controls');
- if (contentId) {
- window.sessionStorage.setItem(contentId, isExpanded.toString());
- }
- }
+ if (!this.config.rememberExpanded) {
+ return;
+ }
+ const id = this.getIdentifier($section);
+ if (id) {
+ try {
+ window.sessionStorage.setItem(id, isExpanded.toString());
+ } catch (exception) {}
}
}
setInitialState($section) {
- if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
- const $button = $section.querySelector(`.${this.sectionButtonClass}`);
- if ($button) {
- const contentId = $button.getAttribute('aria-controls');
- const contentState = contentId ? window.sessionStorage.getItem(contentId) : null;
- if (contentState !== null) {
- this.setExpanded(contentState === 'true', $section);
+ if (!this.config.rememberExpanded) {
+ return;
+ }
+ const id = this.getIdentifier($section);
+ if (id) {
+ try {
+ const state = window.sessionStorage.getItem(id);
+ if (state !== null) {
+ this.setExpanded(state === 'true', $section);
}
- }
+ } catch (exception) {}
}
}
getButtonPunctuationEl() {
@@ -704,47 +719,6 @@
return $punctuationEl;
}
}
- Accordion.moduleName = 'govuk-accordion';
- Accordion.defaults = Object.freeze({
- i18n: {
- hideAllSections: 'Hide all sections',
- hideSection: 'Hide',
- hideSectionAriaLabel: 'Hide this section',
- showAllSections: 'Show all sections',
- showSection: 'Show',
- showSectionAriaLabel: 'Show this section'
- },
- rememberExpanded: true
- });
- Accordion.schema = Object.freeze({
- properties: {
- i18n: {
- type: 'object'
- },
- rememberExpanded: {
- type: 'boolean'
- }
- }
- });
- const helper = {
- /**
- * Check for `window.sessionStorage`, and that it actually works.
- *
- * @returns {boolean} True if session storage is available
- */
- checkForSessionStorage: function () {
- const testString = 'this is the test string';
- let result;
- try {
- window.sessionStorage.setItem(testString, testString);
- result = window.sessionStorage.getItem(testString) === testString.toString();
- window.sessionStorage.removeItem(testString);
- return result;
- } catch (exception) {
- return false;
- }
- }
- };
/**
* Accordion config
@@ -782,6 +756,28 @@
/**
* @typedef {import('../../common/index.mjs').Schema} Schema
*/
+ Accordion.moduleName = 'govuk-accordion';
+ Accordion.defaults = Object.freeze({
+ i18n: {
+ hideAllSections: 'Hide all sections',
+ hideSection: 'Hide',
+ hideSectionAriaLabel: 'Hide this section',
+ showAllSections: 'Show all sections',
+ showSection: 'Show',
+ showSectionAriaLabel: 'Show this section'
+ },
+ rememberExpanded: true
+ });
+ Accordion.schema = Object.freeze({
+ properties: {
+ i18n: {
+ type: 'object'
+ },
+ rememberExpanded: {
+ type: 'boolean'
+ }
+ }
+ });
const DEBOUNCE_TIMEOUT_IN_SECONDS = 1;
diff --git a/packages/govuk-frontend/dist/govuk/all.bundle.mjs b/packages/govuk-frontend/dist/govuk/all.bundle.mjs
index cbc00c0b8..3d03f5f0f 100644
--- a/packages/govuk-frontend/dist/govuk/all.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/all.bundle.mjs
@@ -467,7 +467,6 @@ class Accordion extends GOVUKFrontendComponent {
this.sectionSummaryFocusClass = 'govuk-accordion__section-summary-focus';
this.sectionContentClass = 'govuk-accordion__section-content';
this.$sections = void 0;
- this.browserSupportsSessionStorage = false;
this.$showAllButton = null;
this.$showAllIcon = null;
this.$showAllText = null;
@@ -489,7 +488,6 @@ class Accordion extends GOVUKFrontendComponent {
});
}
this.$sections = $sections;
- this.browserSupportsSessionStorage = helper.checkForSessionStorage();
this.initControls();
this.initSectionHeaders();
this.updateShowAllButton(this.areAllSectionsOpen());
@@ -668,27 +666,44 @@ class Accordion extends GOVUKFrontendComponent {
this.$showAllText.textContent = expanded ? this.i18n.t('hideAllSections') : this.i18n.t('showAllSections');
this.$showAllIcon.classList.toggle(this.downChevronIconClass, !expanded);
}
+
+ /**
+ * Get the identifier for a section
+ *
+ * We need a unique way of identifying each content in the Accordion.
+ * Since an `#id` should be unique and an `id` is required for `aria-`
+ * attributes `id` can be safely used.
+ *
+ * @param {Element} $section - Section element
+ * @returns {string | undefined | null} Identifier for section
+ */
+ getIdentifier($section) {
+ const $button = $section.querySelector(`.${this.sectionButtonClass}`);
+ return $button == null ? void 0 : $button.getAttribute('aria-controls');
+ }
storeState($section, isExpanded) {
- if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
- const $button = $section.querySelector(`.${this.sectionButtonClass}`);
- if ($button) {
- const contentId = $button.getAttribute('aria-controls');
- if (contentId) {
- window.sessionStorage.setItem(contentId, isExpanded.toString());
- }
- }
+ if (!this.config.rememberExpanded) {
+ return;
+ }
+ const id = this.getIdentifier($section);
+ if (id) {
+ try {
+ window.sessionStorage.setItem(id, isExpanded.toString());
+ } catch (exception) {}
}
}
setInitialState($section) {
- if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
- const $button = $section.querySelector(`.${this.sectionButtonClass}`);
- if ($button) {
- const contentId = $button.getAttribute('aria-controls');
- const contentState = contentId ? window.sessionStorage.getItem(contentId) : null;
- if (contentState !== null) {
- this.setExpanded(contentState === 'true', $section);
+ if (!this.config.rememberExpanded) {
+ return;
+ }
+ const id = this.getIdentifier($section);
+ if (id) {
+ try {
+ const state = window.sessionStorage.getItem(id);
+ if (state !== null) {
+ this.setExpanded(state === 'true', $section);
}
- }
+ } catch (exception) {}
}
}
getButtonPunctuationEl() {
@@ -698,47 +713,6 @@ class Accordion extends GOVUKFrontendComponent {
return $punctuationEl;
}
}
-Accordion.moduleName = 'govuk-accordion';
-Accordion.defaults = Object.freeze({
- i18n: {
- hideAllSections: 'Hide all sections',
- hideSection: 'Hide',
- hideSectionAriaLabel: 'Hide this section',
- showAllSections: 'Show all sections',
- showSection: 'Show',
- showSectionAriaLabel: 'Show this section'
- },
- rememberExpanded: true
-});
-Accordion.schema = Object.freeze({
- properties: {
- i18n: {
- type: 'object'
- },
- rememberExpanded: {
- type: 'boolean'
- }
- }
-});
-const helper = {
- /**
- * Check for `window.sessionStorage`, and that it actually works.
- *
- * @returns {boolean} True if session storage is available
- */
- checkForSessionStorage: function () {
- const testString = 'this is the test string';
- let result;
- try {
- window.sessionStorage.setItem(testString, testString);
- result = window.sessionStorage.getItem(testString) === testString.toString();
- window.sessionStorage.removeItem(testString);
- return result;
- } catch (exception) {
- return false;
- }
- }
-};
/**
* Accordion config
@@ -776,6 +750,28 @@ const helper = {
/**
* @typedef {import('../../common/index.mjs').Schema} Schema
*/
+Accordion.moduleName = 'govuk-accordion';
+Accordion.defaults = Object.freeze({
+ i18n: {
+ hideAllSections: 'Hide all sections',
+ hideSection: 'Hide',
+ hideSectionAriaLabel: 'Hide this section',
+ showAllSections: 'Show all sections',
+ showSection: 'Show',
+ showSectionAriaLabel: 'Show this section'
+ },
+ rememberExpanded: true
+});
+Accordion.schema = Object.freeze({
+ properties: {
+ i18n: {
+ type: 'object'
+ },
+ rememberExpanded: {
+ type: 'boolean'
+ }
+ }
+});
const DEBOUNCE_TIMEOUT_IN_SECONDS = 1;
diff --git a/packages/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js b/packages/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js
index 3dcdb7217..312229a64 100644
--- a/packages/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js
@@ -407,7 +407,6 @@
this.sectionSummaryFocusClass = 'govuk-accordion__section-summary-focus';
this.sectionContentClass = 'govuk-accordion__section-content';
this.$sections = void 0;
- this.browserSupportsSessionStorage = false;
this.$showAllButton = null;
this.$showAllIcon = null;
this.$showAllText = null;
@@ -429,7 +428,6 @@
});
}
this.$sections = $sections;
- this.browserSupportsSessionStorage = helper.checkForSessionStorage();
this.initControls();
this.initSectionHeaders();
this.updateShowAllButton(this.areAllSectionsOpen());
@@ -608,27 +606,44 @@
this.$showAllText.textContent = expanded ? this.i18n.t('hideAllSections') : this.i18n.t('showAllSections');
this.$showAllIcon.classList.toggle(this.downChevronIconClass, !expanded);
}
+
+ /**
+ * Get the identifier for a section
+ *
+ * We need a unique way of identifying each content in the Accordion.
+ * Since an `#id` should be unique and an `id` is required for `aria-`
+ * attributes `id` can be safely used.
+ *
+ * @param {Element} $section - Section element
+ * @returns {string | undefined | null} Identifier for section
+ */
+ getIdentifier($section) {
+ const $button = $section.querySelector(`.${this.sectionButtonClass}`);
+ return $button == null ? void 0 : $button.getAttribute('aria-controls');
+ }
storeState($section, isExpanded) {
- if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
- const $button = $section.querySelector(`.${this.sectionButtonClass}`);
- if ($button) {
- const contentId = $button.getAttribute('aria-controls');
- if (contentId) {
- window.sessionStorage.setItem(contentId, isExpanded.toString());
- }
- }
+ if (!this.config.rememberExpanded) {
+ return;
+ }
+ const id = this.getIdentifier($section);
+ if (id) {
+ try {
+ window.sessionStorage.setItem(id, isExpanded.toString());
+ } catch (exception) {}
}
}
setInitialState($section) {
- if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
- const $button = $section.querySelector(`.${this.sectionButtonClass}`);
- if ($button) {
- const contentId = $button.getAttribute('aria-controls');
- const contentState = contentId ? window.sessionStorage.getItem(contentId) : null;
- if (contentState !== null) {
- this.setExpanded(contentState === 'true', $section);
+ if (!this.config.rememberExpanded) {
+ return;
+ }
+ const id = this.getIdentifier($section);
+ if (id) {
+ try {
+ const state = window.sessionStorage.getItem(id);
+ if (state !== null) {
+ this.setExpanded(state === 'true', $section);
}
- }
+ } catch (exception) {}
}
}
getButtonPunctuationEl() {
@@ -638,47 +653,6 @@
return $punctuationEl;
}
}
- Accordion.moduleName = 'govuk-accordion';
- Accordion.defaults = Object.freeze({
- i18n: {
- hideAllSections: 'Hide all sections',
- hideSection: 'Hide',
- hideSectionAriaLabel: 'Hide this section',
- showAllSections: 'Show all sections',
- showSection: 'Show',
- showSectionAriaLabel: 'Show this section'
- },
- rememberExpanded: true
- });
- Accordion.schema = Object.freeze({
- properties: {
- i18n: {
- type: 'object'
- },
- rememberExpanded: {
- type: 'boolean'
- }
- }
- });
- const helper = {
- /**
- * Check for `window.sessionStorage`, and that it actually works.
- *
- * @returns {boolean} True if session storage is available
- */
- checkForSessionStorage: function () {
- const testString = 'this is the test string';
- let result;
- try {
- window.sessionStorage.setItem(testString, testString);
- result = window.sessionStorage.getItem(testString) === testString.toString();
- window.sessionStorage.removeItem(testString);
- return result;
- } catch (exception) {
- return false;
- }
- }
- };
/**
* Accordion config
@@ -716,6 +690,28 @@
/**
* @typedef {import('../../common/index.mjs').Schema} Schema
*/
+ Accordion.moduleName = 'govuk-accordion';
+ Accordion.defaults = Object.freeze({
+ i18n: {
+ hideAllSections: 'Hide all sections',
+ hideSection: 'Hide',
+ hideSectionAriaLabel: 'Hide this section',
+ showAllSections: 'Show all sections',
+ showSection: 'Show',
+ showSectionAriaLabel: 'Show this section'
+ },
+ rememberExpanded: true
+ });
+ Accordion.schema = Object.freeze({
+ properties: {
+ i18n: {
+ type: 'object'
+ },
+ rememberExpanded: {
+ type: 'boolean'
+ }
+ }
+ });
exports.Accordion = Accordion;
diff --git a/packages/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs
index c78c0e64e..de8349632 100644
--- a/packages/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs
@@ -401,7 +401,6 @@ class Accordion extends GOVUKFrontendComponent {
this.sectionSummaryFocusClass = 'govuk-accordion__section-summary-focus';
this.sectionContentClass = 'govuk-accordion__section-content';
this.$sections = void 0;
- this.browserSupportsSessionStorage = false;
this.$showAllButton = null;
this.$showAllIcon = null;
this.$showAllText = null;
@@ -423,7 +422,6 @@ class Accordion extends GOVUKFrontendComponent {
});
}
this.$sections = $sections;
- this.browserSupportsSessionStorage = helper.checkForSessionStorage();
this.initControls();
this.initSectionHeaders();
this.updateShowAllButton(this.areAllSectionsOpen());
@@ -602,27 +600,44 @@ class Accordion extends GOVUKFrontendComponent {
this.$showAllText.textContent = expanded ? this.i18n.t('hideAllSections') : this.i18n.t('showAllSections');
this.$showAllIcon.classList.toggle(this.downChevronIconClass, !expanded);
}
+
+ /**
+ * Get the identifier for a section
+ *
+ * We need a unique way of identifying each content in the Accordion.
+ * Since an `#id` should be unique and an `id` is required for `aria-`
+ * attributes `id` can be safely used.
+ *
+ * @param {Element} $section - Section element
+ * @returns {string | undefined | null} Identifier for section
+ */
+ getIdentifier($section) {
+ const $button = $section.querySelector(`.${this.sectionButtonClass}`);
+ return $button == null ? void 0 : $button.getAttribute('aria-controls');
+ }
storeState($section, isExpanded) {
- if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
- const $button = $section.querySelector(`.${this.sectionButtonClass}`);
- if ($button) {
- const contentId = $button.getAttribute('aria-controls');
- if (contentId) {
- window.sessionStorage.setItem(contentId, isExpanded.toString());
- }
- }
+ if (!this.config.rememberExpanded) {
+ return;
+ }
+ const id = this.getIdentifier($section);
+ if (id) {
+ try {
+ window.sessionStorage.setItem(id, isExpanded.toString());
+ } catch (exception) {}
}
}
setInitialState($section) {
- if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
- const $button = $section.querySelector(`.${this.sectionButtonClass}`);
- if ($button) {
- const contentId = $button.getAttribute('aria-controls');
- const contentState = contentId ? window.sessionStorage.getItem(contentId) : null;
- if (contentState !== null) {
- this.setExpanded(contentState === 'true', $section);
+ if (!this.config.rememberExpanded) {
+ return;
+ }
+ const id = this.getIdentifier($section);
+ if (id) {
+ try {
+ const state = window.sessionStorage.getItem(id);
+ if (state !== null) {
+ this.setExpanded(state === 'true', $section);
}
- }
+ } catch (exception) {}
}
}
getButtonPunctuationEl() {
@@ -632,47 +647,6 @@ class Accordion extends GOVUKFrontendComponent {
return $punctuationEl;
}
}
-Accordion.moduleName = 'govuk-accordion';
-Accordion.defaults = Object.freeze({
- i18n: {
- hideAllSections: 'Hide all sections',
- hideSection: 'Hide',
- hideSectionAriaLabel: 'Hide this section',
- showAllSections: 'Show all sections',
- showSection: 'Show',
- showSectionAriaLabel: 'Show this section'
- },
- rememberExpanded: true
-});
-Accordion.schema = Object.freeze({
- properties: {
- i18n: {
- type: 'object'
- },
- rememberExpanded: {
- type: 'boolean'
- }
- }
-});
-const helper = {
- /**
- * Check for `window.sessionStorage`, and that it actually works.
- *
- * @returns {boolean} True if session storage is available
- */
- checkForSessionStorage: function () {
- const testString = 'this is the test string';
- let result;
- try {
- window.sessionStorage.setItem(testString, testString);
- result = window.sessionStorage.getItem(testString) === testString.toString();
- window.sessionStorage.removeItem(testString);
- return result;
- } catch (exception) {
- return false;
- }
- }
-};
/**
* Accordion config
@@ -710,6 +684,28 @@ const helper = {
/**
* @typedef {import('../../common/index.mjs').Schema} Schema
*/
+Accordion.moduleName = 'govuk-accordion';
+Accordion.defaults = Object.freeze({
+ i18n: {
+ hideAllSections: 'Hide all sections',
+ hideSection: 'Hide',
+ hideSectionAriaLabel: 'Hide this section',
+ showAllSections: 'Show all sections',
+ showSection: 'Show',
+ showSectionAriaLabel: 'Show this section'
+ },
+ rememberExpanded: true
+});
+Accordion.schema = Object.freeze({
+ properties: {
+ i18n: {
+ type: 'object'
+ },
+ rememberExpanded: {
+ type: 'boolean'
+ }
+ }
+});
export { Accordion };
//# sourceMappingURL=accordion.bundle.mjs.map
diff --git a/packages/govuk-frontend/dist/govuk/components/accordion/accordion.mjs b/packages/govuk-frontend/dist/govuk/components/accordion/accordion.mjs
index 86d7fc295..990abb949 100644
--- a/packages/govuk-frontend/dist/govuk/components/accordion/accordion.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/accordion/accordion.mjs
@@ -48,7 +48,6 @@ class Accordion extends GOVUKFrontendComponent {
this.sectionSummaryFocusClass = 'govuk-accordion__section-summary-focus';
this.sectionContentClass = 'govuk-accordion__section-content';
this.$sections = void 0;
- this.browserSupportsSessionStorage = false;
this.$showAllButton = null;
this.$showAllIcon = null;
this.$showAllText = null;
@@ -70,7 +69,6 @@ class Accordion extends GOVUKFrontendComponent {
});
}
this.$sections = $sections;
- this.browserSupportsSessionStorage = helper.checkForSessionStorage();
this.initControls();
this.initSectionHeaders();
this.updateShowAllButton(this.areAllSectionsOpen());
@@ -249,27 +247,44 @@ class Accordion extends GOVUKFrontendComponent {
this.$showAllText.textContent = expanded ? this.i18n.t('hideAllSections') : this.i18n.t('showAllSections');
this.$showAllIcon.classList.toggle(this.downChevronIconClass, !expanded);
}
+
+ /**
+ * Get the identifier for a section
+ *
+ * We need a unique way of identifying each content in the Accordion.
+ * Since an `#id` should be unique and an `id` is required for `aria-`
+ * attributes `id` can be safely used.
+ *
+ * @param {Element} $section - Section element
+ * @returns {string | undefined | null} Identifier for section
+ */
+ getIdentifier($section) {
+ const $button = $section.querySelector(`.${this.sectionButtonClass}`);
+ return $button == null ? void 0 : $button.getAttribute('aria-controls');
+ }
storeState($section, isExpanded) {
- if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
- const $button = $section.querySelector(`.${this.sectionButtonClass}`);
- if ($button) {
- const contentId = $button.getAttribute('aria-controls');
- if (contentId) {
- window.sessionStorage.setItem(contentId, isExpanded.toString());
- }
- }
+ if (!this.config.rememberExpanded) {
+ return;
+ }
+ const id = this.getIdentifier($section);
+ if (id) {
+ try {
+ window.sessionStorage.setItem(id, isExpanded.toString());
+ } catch (exception) {}
}
}
setInitialState($section) {
- if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
- const $button = $section.querySelector(`.${this.sectionButtonClass}`);
- if ($button) {
- const contentId = $button.getAttribute('aria-controls');
- const contentState = contentId ? window.sessionStorage.getItem(contentId) : null;
- if (contentState !== null) {
- this.setExpanded(contentState === 'true', $section);
+ if (!this.config.rememberExpanded) {
+ return;
+ }
+ const id = this.getIdentifier($section);
+ if (id) {
+ try {
+ const state = window.sessionStorage.getItem(id);
+ if (state !== null) {
+ this.setExpanded(state === 'true', $section);
}
- }
+ } catch (exception) {}
}
}
getButtonPunctuationEl() {
@@ -279,47 +294,6 @@ class Accordion extends GOVUKFrontendComponent {
return $punctuationEl;
}
}
-Accordion.moduleName = 'govuk-accordion';
-Accordion.defaults = Object.freeze({
- i18n: {
- hideAllSections: 'Hide all sections',
- hideSection: 'Hide',
- hideSectionAriaLabel: 'Hide this section',
- showAllSections: 'Show all sections',
- showSection: 'Show',
- showSectionAriaLabel: 'Show this section'
- },
- rememberExpanded: true
-});
-Accordion.schema = Object.freeze({
- properties: {
- i18n: {
- type: 'object'
- },
- rememberExpanded: {
- type: 'boolean'
- }
- }
-});
-const helper = {
- /**
- * Check for `window.sessionStorage`, and that it actually works.
- *
- * @returns {boolean} True if session storage is available
- */
- checkForSessionStorage: function () {
- const testString = 'this is the test string';
- let result;
- try {
- window.sessionStorage.setItem(testString, testString);
- result = window.sessionStorage.getItem(testString) === testString.toString();
- window.sessionStorage.removeItem(testString);
- return result;
- } catch (exception) {
- return false;
- }
- }
-};
/**
* Accordion config
@@ -357,6 +331,28 @@ const helper = {
/**
* @typedef {import('../../common/index.mjs').Schema} Schema
*/
+Accordion.moduleName = 'govuk-accordion';
+Accordion.defaults = Object.freeze({
+ i18n: {
+ hideAllSections: 'Hide all sections',
+ hideSection: 'Hide',
+ hideSectionAriaLabel: 'Hide this section',
+ showAllSections: 'Show all sections',
+ showSection: 'Show',
+ showSectionAriaLabel: 'Show this section'
+ },
+ rememberExpanded: true
+});
+Accordion.schema = Object.freeze({
+ properties: {
+ i18n: {
+ type: 'object'
+ },
+ rememberExpanded: {
+ type: 'boolean'
+ }
+ }
+});
export { Accordion };
//# sourceMappingURL=accordion.mjs.map
Action run for df11d0b |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me.
I have a mild recollection, somewhere in the recesses of the mind, that localStorage
/sessionStorage
can—in some circumstances—appear to be available APIs, but they will refuse to store or retrieve anything if you actually try to use it.
That was probably due to some sort of private browsing mode. I imagine this is why the helper function explicitly tested for this scenario.
However, I'm okay with that being removed in this situation as the fail state would be that the expanded sections don't get remembered, which feels acceptably still-functional.
2830480
to
bed231c
Compare
We don’t do anything different if we detect the browser doesn’t support session storage, so we don’t really care. We do need to wrap attempts to set *or get* from sessions storage in try blocks because setItem can throw `QuotaExceededError` exceptions [1] and some older browsers will throw other exceptions if session storage isn’t available (disabled, or using private browsing) [2] [3] However we don’t need to do anything different if exceptions are thrown – we can safely catch those exceptions and swallow them. [1]: https://html.spec.whatwg.org/multipage/webstorage.html#dom-storage-setitem [2]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#feature-detecting_localstorage [3]: https://gist.github.com/paulirish/5558557
e1e7e26
to
a9ffec4
Compare
We don’t do anything different if we detect the browser doesn’t support session storage, so we don’t really need to care whether it works or not.
We do need to wrap attempts to set or get from sessions storage in try blocks because setItem can throw
QuotaExceededError
exceptions and some older browsers will throw other exceptions if session storage isn’t available (disabled, or using private browsing)However we don’t need to do anything different if exceptions are thrown – we can safely catch those exceptions and swallow them.