Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

init all on error #5273

Closed
wants to merge 1 commit into from
Closed

Conversation

patrickpatrickpatrick
Copy link
Contributor

@patrickpatrickpatrick patrickpatrickpatrick commented Aug 29, 2024

Fixes #5267

  • Add isSupported to all.mjs
  • Add isSupported to createAll
  • Add errorCallback to createAll

Copy link

github-actions bot commented Aug 29, 2024

📋 Stats

File sizes

File Size
dist/govuk-frontend-development.min.css 112.61 KiB
dist/govuk-frontend-development.min.js 42.12 KiB
packages/govuk-frontend/dist/govuk/all.bundle.js 89.55 KiB
packages/govuk-frontend/dist/govuk/all.bundle.mjs 84.1 KiB
packages/govuk-frontend/dist/govuk/all.mjs 1.01 KiB
packages/govuk-frontend/dist/govuk/govuk-frontend-component.mjs 359 B
packages/govuk-frontend/dist/govuk/govuk-frontend.min.css 112.6 KiB
packages/govuk-frontend/dist/govuk/govuk-frontend.min.js 42.11 KiB
packages/govuk-frontend/dist/govuk/i18n.mjs 5.55 KiB
packages/govuk-frontend/dist/govuk/init.mjs 6.59 KiB

Modules

File Size (bundled) Size (minified)
all.mjs 80.49 KiB 40.06 KiB
accordion.mjs 23.83 KiB 12.39 KiB
button.mjs 6.31 KiB 2.69 KiB
character-count.mjs 22.73 KiB 9.92 KiB
checkboxes.mjs 6.16 KiB 2.83 KiB
error-summary.mjs 8.22 KiB 3.46 KiB
exit-this-page.mjs 17.43 KiB 9.26 KiB
header.mjs 4.79 KiB 2.6 KiB
notification-banner.mjs 6.59 KiB 2.62 KiB
password-input.mjs 15.48 KiB 7.25 KiB
radios.mjs 5.16 KiB 2.38 KiB
skip-link.mjs 4.72 KiB 2.18 KiB
tabs.mjs 10.38 KiB 6.06 KiB

View stats and visualisations on the review app


Action run for 1fc0977

Copy link

github-actions bot commented Aug 29, 2024

JavaScript changes to npm package

diff --git a/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js b/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js
index bc47ebb0c..dd7574fa1 100644
--- a/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js
+++ b/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js
@@ -1104,15 +1104,26 @@ function initAll(e) {
     }))
 }
 
-function createAll(e, t, n = document) {
-    const i = n.querySelectorAll(`[data-module="${e.moduleName}"]`);
-    return Array.from(i).map((n => {
+function createAll(e, t, n) {
+    let i, s = document;
+    var o;
+    "object" == typeof n && (s = null != (o = n.scope) ? o : s, i = n.onError);
+    "function" == typeof n && (i = n), n instanceof HTMLElement && (s = n);
+    const r = s.querySelectorAll(`[data-module="${e.moduleName}"]`);
+    return isSupported() ? Array.from(r).map((n => {
         try {
             return "defaults" in e && void 0 !== t ? new e(n, t) : new e(n)
-        } catch (i) {
-            return console.log(i), null
+        } catch (s) {
+            return i && s instanceof Error ? i(s, {
+                element: n,
+                component: e,
+                config: t
+            }) : console.log(s), null
         }
-    })).filter(Boolean)
+    })).filter(Boolean) : (i ? i(new SupportError, {
+        component: e,
+        config: t
+    }) : console.log(new SupportError), [])
 }
 Tabs.moduleName = "govuk-tabs";
 export {
@@ -1130,5 +1141,6 @@ export {
     Tabs,
     createAll,
     initAll,
+    isSupported,
     version
 }; //# sourceMappingURL=govuk-frontend.min.js.map
\ No newline at end of file

Action run for 1fc0977

Copy link

github-actions bot commented Aug 29, 2024

Other changes to npm package

diff --git a/packages/govuk-frontend/dist/govuk/all.bundle.js b/packages/govuk-frontend/dist/govuk/all.bundle.js
index 1bccdae71..057ec0db2 100644
--- a/packages/govuk-frontend/dist/govuk/all.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/all.bundle.js
@@ -114,6 +114,16 @@
     (_options$onBeforeFocu = options.onBeforeFocus) == null || _options$onBeforeFocu.call($element);
     $element.focus();
   }
+
+  /**
+   * Checks if GOV.UK Frontend is supported on this page
+   *
+   * Some browsers will load and run our JavaScript but GOV.UK Frontend
+   * won't be supported.
+   *
+   * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+   * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+   */
   function isSupported($scope = document.body) {
     if (!$scope) {
       return false;
@@ -2373,17 +2383,50 @@
    *
    * @template {CompatibleClass} T
    * @param {T} Component - class of the component to create
-   * @param {T["defaults"]} [config] - config for the component
-   * @param {Element|Document} [$scope] - scope of the document to search within
+   * @param {T["defaults"]} [config] - Config supplied to component
+   * @param {OnErrorCallback<T> | Element | Document | CreateAllOptions<T> } [createAllOptions] - options for createAll including scope of the document to search within and callback function if error throw by component on init
    * @returns {Array<InstanceType<T>>} - array of instantiated components
    */
-  function createAll(Component, config, $scope = document) {
+  function createAll(Component, config, createAllOptions) {
+    let $scope = document;
+    let onError;
+    if (typeof createAllOptions === 'object') {
+      var _createAllOptions$sco;
+      createAllOptions = createAllOptions;
+      $scope = (_createAllOptions$sco = createAllOptions.scope) != null ? _createAllOptions$sco : $scope;
+      onError = createAllOptions.onError;
+    }
+    if (typeof createAllOptions === 'function') {
+      onError = createAllOptions;
+    }
+    if (createAllOptions instanceof HTMLElement) {
+      $scope = createAllOptions;
+    }
     const $elements = $scope.querySelectorAll(`[data-module="${Component.moduleName}"]`);
+    if (!isSupported()) {
+      if (onError) {
+        onError(new SupportError(), {
+          component: Component,
+          config
+        });
+      } else {
+        console.log(new SupportError());
+      }
+      return [];
+    }
     return Array.from($elements).map($element => {
       try {
         return 'defaults' in Component && typeof config !== 'undefined' ? new Component($element, config) : new Component($element);
       } catch (error) {
-        console.log(error);
+        if (onError && error instanceof Error) {
+          onError(error, {
+            element: $element,
+            component: Component,
+            config
+          });
+        } else {
+          console.log(error);
+        }
         return null;
       }
     }).filter(Boolean);
@@ -2422,6 +2465,25 @@
    *
    * @typedef {keyof Config} ConfigKey
    */
+  /**
+   * @template {CompatibleClass} T
+   * @typedef {object} ErrorContext
+   * @property {Element} [element] - Element used for component module initialisation
+   * @property {T} component - Class of component
+   * @property {T["defaults"]} config - Config supplied to component
+   */
+  /**
+   * @template {CompatibleClass} T
+   * @callback OnErrorCallback
+   * @param {Error} error - Thrown error
+   * @param {ErrorContext<T>} context - Object containing the element, component class and configuration
+   */
+  /**
+   * @template {CompatibleClass} T
+   * @typedef {object} CreateAllOptions
+   * @property {Element | Document} [scope] - scope of the document to search within
+   * @property {OnErrorCallback<T>} [onError] - callback function if error throw by component on init
+   */
 
   exports.Accordion = Accordion;
   exports.Button = Button;
@@ -2437,6 +2499,7 @@
   exports.Tabs = Tabs;
   exports.createAll = createAll;
   exports.initAll = initAll;
+  exports.isSupported = isSupported;
   exports.version = version;
 
 }));
diff --git a/packages/govuk-frontend/dist/govuk/all.bundle.mjs b/packages/govuk-frontend/dist/govuk/all.bundle.mjs
index bec0c33e5..15a7feada 100644
--- a/packages/govuk-frontend/dist/govuk/all.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/all.bundle.mjs
@@ -108,6 +108,16 @@ function setFocus($element, options = {}) {
   (_options$onBeforeFocu = options.onBeforeFocus) == null || _options$onBeforeFocu.call($element);
   $element.focus();
 }
+
+/**
+ * Checks if GOV.UK Frontend is supported on this page
+ *
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
+ * won't be supported.
+ *
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+ */
 function isSupported($scope = document.body) {
   if (!$scope) {
     return false;
@@ -2367,17 +2377,50 @@ function initAll(config) {
  *
  * @template {CompatibleClass} T
  * @param {T} Component - class of the component to create
- * @param {T["defaults"]} [config] - config for the component
- * @param {Element|Document} [$scope] - scope of the document to search within
+ * @param {T["defaults"]} [config] - Config supplied to component
+ * @param {OnErrorCallback<T> | Element | Document | CreateAllOptions<T> } [createAllOptions] - options for createAll including scope of the document to search within and callback function if error throw by component on init
  * @returns {Array<InstanceType<T>>} - array of instantiated components
  */
-function createAll(Component, config, $scope = document) {
+function createAll(Component, config, createAllOptions) {
+  let $scope = document;
+  let onError;
+  if (typeof createAllOptions === 'object') {
+    var _createAllOptions$sco;
+    createAllOptions = createAllOptions;
+    $scope = (_createAllOptions$sco = createAllOptions.scope) != null ? _createAllOptions$sco : $scope;
+    onError = createAllOptions.onError;
+  }
+  if (typeof createAllOptions === 'function') {
+    onError = createAllOptions;
+  }
+  if (createAllOptions instanceof HTMLElement) {
+    $scope = createAllOptions;
+  }
   const $elements = $scope.querySelectorAll(`[data-module="${Component.moduleName}"]`);
+  if (!isSupported()) {
+    if (onError) {
+      onError(new SupportError(), {
+        component: Component,
+        config
+      });
+    } else {
+      console.log(new SupportError());
+    }
+    return [];
+  }
   return Array.from($elements).map($element => {
     try {
       return 'defaults' in Component && typeof config !== 'undefined' ? new Component($element, config) : new Component($element);
     } catch (error) {
-      console.log(error);
+      if (onError && error instanceof Error) {
+        onError(error, {
+          element: $element,
+          component: Component,
+          config
+        });
+      } else {
+        console.log(error);
+      }
       return null;
     }
   }).filter(Boolean);
@@ -2416,6 +2459,25 @@ function createAll(Component, config, $scope = document) {
  *
  * @typedef {keyof Config} ConfigKey
  */
+/**
+ * @template {CompatibleClass} T
+ * @typedef {object} ErrorContext
+ * @property {Element} [element] - Element used for component module initialisation
+ * @property {T} component - Class of component
+ * @property {T["defaults"]} config - Config supplied to component
+ */
+/**
+ * @template {CompatibleClass} T
+ * @callback OnErrorCallback
+ * @param {Error} error - Thrown error
+ * @param {ErrorContext<T>} context - Object containing the element, component class and configuration
+ */
+/**
+ * @template {CompatibleClass} T
+ * @typedef {object} CreateAllOptions
+ * @property {Element | Document} [scope] - scope of the document to search within
+ * @property {OnErrorCallback<T>} [onError] - callback function if error throw by component on init
+ */
 
-export { Accordion, Button, CharacterCount, Checkboxes, ErrorSummary, ExitThisPage, Header, NotificationBanner, PasswordInput, Radios, SkipLink, Tabs, createAll, initAll, version };
+export { Accordion, Button, CharacterCount, Checkboxes, ErrorSummary, ExitThisPage, Header, NotificationBanner, PasswordInput, Radios, SkipLink, Tabs, createAll, initAll, isSupported, version };
 //# sourceMappingURL=all.bundle.mjs.map
diff --git a/packages/govuk-frontend/dist/govuk/all.mjs b/packages/govuk-frontend/dist/govuk/all.mjs
index e395113b0..b254f0ce9 100644
--- a/packages/govuk-frontend/dist/govuk/all.mjs
+++ b/packages/govuk-frontend/dist/govuk/all.mjs
@@ -12,4 +12,5 @@ export { Radios } from './components/radios/radios.mjs';
 export { SkipLink } from './components/skip-link/skip-link.mjs';
 export { Tabs } from './components/tabs/tabs.mjs';
 export { createAll, initAll } from './init.mjs';
+export { isSupported } from './common/index.mjs';
 //# sourceMappingURL=all.mjs.map
diff --git a/packages/govuk-frontend/dist/govuk/common/index.mjs b/packages/govuk-frontend/dist/govuk/common/index.mjs
index 8b1e29b27..f1259e9dd 100644
--- a/packages/govuk-frontend/dist/govuk/common/index.mjs
+++ b/packages/govuk-frontend/dist/govuk/common/index.mjs
@@ -79,6 +79,16 @@ function setFocus($element, options = {}) {
   (_options$onBeforeFocu = options.onBeforeFocus) == null || _options$onBeforeFocu.call($element);
   $element.focus();
 }
+
+/**
+ * Checks if GOV.UK Frontend is supported on this page
+ *
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
+ * won't be supported.
+ *
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+ */
 function isSupported($scope = document.body) {
   if (!$scope) {
     return false;
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 312229a64..d9a9f6fb4 100644
--- a/packages/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js
@@ -74,6 +74,16 @@
     }
     return newObject[namespace];
   }
+
+  /**
+   * Checks if GOV.UK Frontend is supported on this page
+   *
+   * Some browsers will load and run our JavaScript but GOV.UK Frontend
+   * won't be supported.
+   *
+   * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+   * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+   */
   function isSupported($scope = document.body) {
     if (!$scope) {
       return false;
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 de8349632..426470026 100644
--- a/packages/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs
@@ -68,6 +68,16 @@ function extractConfigByNamespace(Component, dataset, namespace) {
   }
   return newObject[namespace];
 }
+
+/**
+ * Checks if GOV.UK Frontend is supported on this page
+ *
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
+ * won't be supported.
+ *
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+ */
 function isSupported($scope = document.body) {
   if (!$scope) {
     return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/button/button.bundle.js b/packages/govuk-frontend/dist/govuk/components/button/button.bundle.js
index d67071a8f..4fa64a9c3 100644
--- a/packages/govuk-frontend/dist/govuk/components/button/button.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/button/button.bundle.js
@@ -74,6 +74,16 @@
     }
     return newObject[namespace];
   }
+
+  /**
+   * Checks if GOV.UK Frontend is supported on this page
+   *
+   * Some browsers will load and run our JavaScript but GOV.UK Frontend
+   * won't be supported.
+   *
+   * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+   * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+   */
   function isSupported($scope = document.body) {
     if (!$scope) {
       return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/button/button.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/button/button.bundle.mjs
index 38af24c35..767533419 100644
--- a/packages/govuk-frontend/dist/govuk/components/button/button.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/button/button.bundle.mjs
@@ -68,6 +68,16 @@ function extractConfigByNamespace(Component, dataset, namespace) {
   }
   return newObject[namespace];
 }
+
+/**
+ * Checks if GOV.UK Frontend is supported on this page
+ *
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
+ * won't be supported.
+ *
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+ */
 function isSupported($scope = document.body) {
   if (!$scope) {
     return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js b/packages/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js
index baeeae62c..3a0f99791 100644
--- a/packages/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js
@@ -79,6 +79,16 @@
     }
     return newObject[namespace];
   }
+
+  /**
+   * Checks if GOV.UK Frontend is supported on this page
+   *
+   * Some browsers will load and run our JavaScript but GOV.UK Frontend
+   * won't be supported.
+   *
+   * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+   * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+   */
   function isSupported($scope = document.body) {
     if (!$scope) {
       return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs
index 473db45b5..411789bab 100644
--- a/packages/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs
@@ -73,6 +73,16 @@ function extractConfigByNamespace(Component, dataset, namespace) {
   }
   return newObject[namespace];
 }
+
+/**
+ * Checks if GOV.UK Frontend is supported on this page
+ *
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
+ * won't be supported.
+ *
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+ */
 function isSupported($scope = document.body) {
   if (!$scope) {
     return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js b/packages/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js
index fa0f0190a..9750c9804 100644
--- a/packages/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js
@@ -40,6 +40,15 @@
     }
   }
 
+  /**
+   * Checks if GOV.UK Frontend is supported on this page
+   *
+   * Some browsers will load and run our JavaScript but GOV.UK Frontend
+   * won't be supported.
+   *
+   * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+   * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+   */
   function isSupported($scope = document.body) {
     if (!$scope) {
       return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs
index f8ab886f3..e6bc6213e 100644
--- a/packages/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs
@@ -34,6 +34,15 @@ class ElementError extends GOVUKFrontendError {
   }
 }
 
+/**
+ * Checks if GOV.UK Frontend is supported on this page
+ *
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
+ * won't be supported.
+ *
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+ */
 function isSupported($scope = document.body) {
   if (!$scope) {
     return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js b/packages/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js
index 32f091022..bf90c6db5 100644
--- a/packages/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js
@@ -104,6 +104,16 @@
     (_options$onBeforeFocu = options.onBeforeFocus) == null || _options$onBeforeFocu.call($element);
     $element.focus();
   }
+
+  /**
+   * Checks if GOV.UK Frontend is supported on this page
+   *
+   * Some browsers will load and run our JavaScript but GOV.UK Frontend
+   * won't be supported.
+   *
+   * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+   * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+   */
   function isSupported($scope = document.body) {
     if (!$scope) {
       return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs
index 900032a18..cb21f83ca 100644
--- a/packages/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs
@@ -98,6 +98,16 @@ function setFocus($element, options = {}) {
   (_options$onBeforeFocu = options.onBeforeFocus) == null || _options$onBeforeFocu.call($element);
   $element.focus();
 }
+
+/**
+ * Checks if GOV.UK Frontend is supported on this page
+ *
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
+ * won't be supported.
+ *
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+ */
 function isSupported($scope = document.body) {
   if (!$scope) {
     return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js b/packages/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js
index bf0fc9157..215fa91f6 100644
--- a/packages/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js
@@ -74,6 +74,16 @@
     }
     return newObject[namespace];
   }
+
+  /**
+   * Checks if GOV.UK Frontend is supported on this page
+   *
+   * Some browsers will load and run our JavaScript but GOV.UK Frontend
+   * won't be supported.
+   *
+   * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+   * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+   */
   function isSupported($scope = document.body) {
     if (!$scope) {
       return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs
index 34b812e2e..8b9ae0812 100644
--- a/packages/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs
@@ -68,6 +68,16 @@ function extractConfigByNamespace(Component, dataset, namespace) {
   }
   return newObject[namespace];
 }
+
+/**
+ * Checks if GOV.UK Frontend is supported on this page
+ *
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
+ * won't be supported.
+ *
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+ */
 function isSupported($scope = document.body) {
   if (!$scope) {
     return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/header/header.bundle.js b/packages/govuk-frontend/dist/govuk/components/header/header.bundle.js
index aa732880f..d1d56b9bc 100644
--- a/packages/govuk-frontend/dist/govuk/components/header/header.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/header/header.bundle.js
@@ -12,6 +12,16 @@
       value: value || undefined
     };
   }
+
+  /**
+   * Checks if GOV.UK Frontend is supported on this page
+   *
+   * Some browsers will load and run our JavaScript but GOV.UK Frontend
+   * won't be supported.
+   *
+   * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+   * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+   */
   function isSupported($scope = document.body) {
     if (!$scope) {
       return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/header/header.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/header/header.bundle.mjs
index 14d66876b..f850fc1f5 100644
--- a/packages/govuk-frontend/dist/govuk/components/header/header.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/header/header.bundle.mjs
@@ -6,6 +6,16 @@ function getBreakpoint(name) {
     value: value || undefined
   };
 }
+
+/**
+ * Checks if GOV.UK Frontend is supported on this page
+ *
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
+ * won't be supported.
+ *
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+ */
 function isSupported($scope = document.body) {
   if (!$scope) {
     return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js b/packages/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js
index e1450e006..e100700c3 100644
--- a/packages/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js
@@ -98,6 +98,16 @@
     (_options$onBeforeFocu = options.onBeforeFocus) == null || _options$onBeforeFocu.call($element);
     $element.focus();
   }
+
+  /**
+   * Checks if GOV.UK Frontend is supported on this page
+   *
+   * Some browsers will load and run our JavaScript but GOV.UK Frontend
+   * won't be supported.
+   *
+   * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+   * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+   */
   function isSupported($scope = document.body) {
     if (!$scope) {
       return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs
index b9bddd534..2016e5f6f 100644
--- a/packages/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs
@@ -92,6 +92,16 @@ function setFocus($element, options = {}) {
   (_options$onBeforeFocu = options.onBeforeFocus) == null || _options$onBeforeFocu.call($element);
   $element.focus();
 }
+
+/**
+ * Checks if GOV.UK Frontend is supported on this page
+ *
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
+ * won't be supported.
+ *
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+ */
 function isSupported($scope = document.body) {
   if (!$scope) {
     return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js b/packages/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js
index 6b195b19c..a72f6fe34 100644
--- a/packages/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js
@@ -79,6 +79,16 @@
     }
     return newObject[namespace];
   }
+
+  /**
+   * Checks if GOV.UK Frontend is supported on this page
+   *
+   * Some browsers will load and run our JavaScript but GOV.UK Frontend
+   * won't be supported.
+   *
+   * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+   * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+   */
   function isSupported($scope = document.body) {
     if (!$scope) {
       return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs
index 14c0f41d4..a05806da4 100644
--- a/packages/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs
@@ -73,6 +73,16 @@ function extractConfigByNamespace(Component, dataset, namespace) {
   }
   return newObject[namespace];
 }
+
+/**
+ * Checks if GOV.UK Frontend is supported on this page
+ *
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
+ * won't be supported.
+ *
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+ */
 function isSupported($scope = document.body) {
   if (!$scope) {
     return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/radios/radios.bundle.js b/packages/govuk-frontend/dist/govuk/components/radios/radios.bundle.js
index 4ade86db5..493e0e50c 100644
--- a/packages/govuk-frontend/dist/govuk/components/radios/radios.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/radios/radios.bundle.js
@@ -40,6 +40,15 @@
     }
   }
 
+  /**
+   * Checks if GOV.UK Frontend is supported on this page
+   *
+   * Some browsers will load and run our JavaScript but GOV.UK Frontend
+   * won't be supported.
+   *
+   * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+   * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+   */
   function isSupported($scope = document.body) {
     if (!$scope) {
       return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs
index fcaf82356..f2f80a00f 100644
--- a/packages/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs
@@ -34,6 +34,15 @@ class ElementError extends GOVUKFrontendError {
   }
 }
 
+/**
+ * Checks if GOV.UK Frontend is supported on this page
+ *
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
+ * won't be supported.
+ *
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+ */
 function isSupported($scope = document.body) {
   if (!$scope) {
     return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js b/packages/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js
index 1e8879f6b..5e5be27e9 100644
--- a/packages/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js
@@ -34,6 +34,16 @@
     (_options$onBeforeFocu = options.onBeforeFocus) == null || _options$onBeforeFocu.call($element);
     $element.focus();
   }
+
+  /**
+   * Checks if GOV.UK Frontend is supported on this page
+   *
+   * Some browsers will load and run our JavaScript but GOV.UK Frontend
+   * won't be supported.
+   *
+   * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+   * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+   */
   function isSupported($scope = document.body) {
     if (!$scope) {
       return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs
index 0b6822202..13441668c 100644
--- a/packages/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs
@@ -28,6 +28,16 @@ function setFocus($element, options = {}) {
   (_options$onBeforeFocu = options.onBeforeFocus) == null || _options$onBeforeFocu.call($element);
   $element.focus();
 }
+
+/**
+ * Checks if GOV.UK Frontend is supported on this page
+ *
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
+ * won't be supported.
+ *
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+ */
 function isSupported($scope = document.body) {
   if (!$scope) {
     return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js b/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js
index 2ec07316d..cb5d7de9c 100644
--- a/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js
@@ -18,6 +18,16 @@
       value: value || undefined
     };
   }
+
+  /**
+   * Checks if GOV.UK Frontend is supported on this page
+   *
+   * Some browsers will load and run our JavaScript but GOV.UK Frontend
+   * won't be supported.
+   *
+   * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+   * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+   */
   function isSupported($scope = document.body) {
     if (!$scope) {
       return false;
diff --git a/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs
index 96cfa7f4f..29d45d0e2 100644
--- a/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs
@@ -12,6 +12,16 @@ function getBreakpoint(name) {
     value: value || undefined
   };
 }
+
+/**
+ * Checks if GOV.UK Frontend is supported on this page
+ *
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
+ * won't be supported.
+ *
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
+ */
 function isSupported($scope = document.body) {
   if (!$scope) {
     return false;
diff --git a/packages/govuk-frontend/dist/govuk/init.mjs b/packages/govuk-frontend/dist/govuk/init.mjs
index f985eaffb..2de2329d5 100644
--- a/packages/govuk-frontend/dist/govuk/init.mjs
+++ b/packages/govuk-frontend/dist/govuk/init.mjs
@@ -46,17 +46,50 @@ function initAll(config) {
  *
  * @template {CompatibleClass} T
  * @param {T} Component - class of the component to create
- * @param {T["defaults"]} [config] - config for the component
- * @param {Element|Document} [$scope] - scope of the document to search within
+ * @param {T["defaults"]} [config] - Config supplied to component
+ * @param {OnErrorCallback<T> | Element | Document | CreateAllOptions<T> } [createAllOptions] - options for createAll including scope of the document to search within and callback function if error throw by component on init
  * @returns {Array<InstanceType<T>>} - array of instantiated components
  */
-function createAll(Component, config, $scope = document) {
+function createAll(Component, config, createAllOptions) {
+  let $scope = document;
+  let onError;
+  if (typeof createAllOptions === 'object') {
+    var _createAllOptions$sco;
+    createAllOptions = createAllOptions;
+    $scope = (_createAllOptions$sco = createAllOptions.scope) != null ? _createAllOptions$sco : $scope;
+    onError = createAllOptions.onError;
+  }
+  if (typeof createAllOptions === 'function') {
+    onError = createAllOptions;
+  }
+  if (createAllOptions instanceof HTMLElement) {
+    $scope = createAllOptions;
+  }
   const $elements = $scope.querySelectorAll(`[data-module="${Component.moduleName}"]`);
+  if (!isSupported()) {
+    if (onError) {
+      onError(new SupportError(), {
+        component: Component,
+        config
+      });
+    } else {
+      console.log(new SupportError());
+    }
+    return [];
+  }
   return Array.from($elements).map($element => {
     try {
       return 'defaults' in Component && typeof config !== 'undefined' ? new Component($element, config) : new Component($element);
     } catch (error) {
-      console.log(error);
+      if (onError && error instanceof Error) {
+        onError(error, {
+          element: $element,
+          component: Component,
+          config
+        });
+      } else {
+        console.log(error);
+      }
       return null;
     }
   }).filter(Boolean);
@@ -95,6 +128,25 @@ function createAll(Component, config, $scope = document) {
  *
  * @typedef {keyof Config} ConfigKey
  */
+/**
+ * @template {CompatibleClass} T
+ * @typedef {object} ErrorContext
+ * @property {Element} [element] - Element used for component module initialisation
+ * @property {T} component - Class of component
+ * @property {T["defaults"]} config - Config supplied to component
+ */
+/**
+ * @template {CompatibleClass} T
+ * @callback OnErrorCallback
+ * @param {Error} error - Thrown error
+ * @param {ErrorContext<T>} context - Object containing the element, component class and configuration
+ */
+/**
+ * @template {CompatibleClass} T
+ * @typedef {object} CreateAllOptions
+ * @property {Element | Document} [scope] - scope of the document to search within
+ * @property {OnErrorCallback<T>} [onError] - callback function if error throw by component on init
+ */
 
 export { createAll, initAll };
 //# sourceMappingURL=init.mjs.map

Action run for 1fc0977

@patrickpatrickpatrick patrickpatrickpatrick changed the base branch from main to public-js-api August 29, 2024 08:43
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-5273 August 29, 2024 08:43 Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add callback to respond to errors when a component does not initialise in initAll
2 participants