@4site/engrid-scripts 0.22.10 → 0.22.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/a11y.d.ts CHANGED
@@ -5,4 +5,5 @@ export declare class A11y {
5
5
  private addLabel;
6
6
  private updateFrequencyLabel;
7
7
  private setAutoGeneratedAltTags;
8
+ private manageErrorListAlertRole;
8
9
  }
package/dist/a11y.js CHANGED
@@ -8,6 +8,7 @@ export class A11y {
8
8
  this.updateFrequencyLabel();
9
9
  const ecardImages = document.querySelectorAll('.en__ecarditems__list img');
10
10
  this.setAutoGeneratedAltTags(ecardImages);
11
+ this.manageErrorListAlertRole();
11
12
  }
12
13
  addGroupRole() {
13
14
  // Add role="group" to all EN Radio fields
@@ -93,4 +94,29 @@ export class A11y {
93
94
  }
94
95
  });
95
96
  }
97
+ manageErrorListAlertRole() {
98
+ const errorList = document.querySelector('ul.en__errorList');
99
+ if (!errorList)
100
+ return;
101
+ const hasErrorItems = () => Boolean(errorList.querySelector('li'));
102
+ const enableAlert = () => {
103
+ if (!errorList.hasAttribute('role')) {
104
+ errorList.setAttribute('role', 'alert');
105
+ }
106
+ };
107
+ const disableAlert = () => {
108
+ if (errorList.hasAttribute('role')) {
109
+ errorList.removeAttribute('role');
110
+ }
111
+ };
112
+ hasErrorItems() ? enableAlert() : disableAlert();
113
+ new MutationObserver(records => {
114
+ for (const record of records) {
115
+ if (record.type === 'childList') {
116
+ hasErrorItems() ? enableAlert() : disableAlert();
117
+ break;
118
+ }
119
+ }
120
+ }).observe(errorList, { childList: true });
121
+ }
96
122
  }
@@ -1,6 +1,64 @@
1
1
  export declare class PageBackground {
2
2
  private pageBackground;
3
+ private mutationObserver;
4
+ private logger;
3
5
  constructor();
6
+ /**
7
+ * Initialize background image by finding and setting CSS custom property
8
+ */
9
+ private initializeBackgroundImage;
10
+ /**
11
+ * Set the background image URL as a CSS custom property
12
+ */
13
+ private setBackgroundImageUrl;
14
+ /**
15
+ * Processes attribution positioning for background images by moving positioning classes
16
+ * and data attributes from images to their parent column containers.
17
+ *
18
+ * This function handles two attribution patterns:
19
+ * 1. Class-based: <img class="attribution-bottomright" src="...">
20
+ * 2. Data attribute-based: <img data-background-position="bottomright" src="...">
21
+ *
22
+ * Examples:
23
+ *
24
+ * Class-based attribution:
25
+ * <img class="attribution-bottomright" src="background.jpg">
26
+ * → Moves "attribution-bottomright" class to parent .en__component--column
27
+ *
28
+ * Data attribute-based attribution:
29
+ * <img data-background-position="top" src="background.jpg">
30
+ * → Converts to "attribution-top" class and moves to parent .en__component--column
31
+ *
32
+ * Supported positioning values:
33
+ * - center
34
+ * - top, topcenter (these result in the same positioning)
35
+ * - right, rightcenter (these result in the same positioning)
36
+ * - bottom, bottomcenter (these result in the same positioning)
37
+ * - left, leftcenter (these result in the same positioning)
38
+ * - topright
39
+ * - bottomright
40
+ * - bottomleft
41
+ * - topleft
42
+ */
43
+ private processAttributionPositioning;
44
+ /**
45
+ * Process attribution for a single image
46
+ */
47
+ private processImageAttribution;
48
+ /**
49
+ * Handle class-based attribution positioning
50
+ */
51
+ private handleClassBasedAttribution;
52
+ /**
53
+ * Handle data attribute-based attribution positioning
54
+ */
55
+ private handleDataAttributeAttribution;
56
+ private setupMutationObserver;
57
+ reprocessAttributionPositioning(): void;
58
+ /**
59
+ * Clean up resources and observers
60
+ */
61
+ destroy(): void;
4
62
  private setDataAttributes;
5
63
  private hasVideoBackground;
6
64
  private hasImageBackground;
@@ -1,55 +1,242 @@
1
- import { ENGrid } from "./engrid";
1
+ import { ENGrid, EngridLogger } from ".";
2
2
  export class PageBackground {
3
3
  constructor() {
4
4
  // @TODO: Change page-backgroundImage to page-background
5
5
  this.pageBackground = document.querySelector(".page-backgroundImage");
6
- // Finds any <img> added to the "backgroundImage" ENGRid section and sets it as the "--engrid__page-backgroundImage_url" CSS Custom Property
7
- if (this.pageBackground) {
8
- const pageBackgroundImg = this.pageBackground.querySelector("img");
9
- let pageBackgroundImgDataSrc = pageBackgroundImg === null || pageBackgroundImg === void 0 ? void 0 : pageBackgroundImg.getAttribute("data-src");
10
- let pageBackgroundImgSrc = pageBackgroundImg === null || pageBackgroundImg === void 0 ? void 0 : pageBackgroundImg.src;
11
- if (this.pageBackground && pageBackgroundImgDataSrc) {
12
- if (ENGrid.debug)
13
- console.log("A background image set in the page was found with a data-src value, setting it as --engrid__page-backgroundImage_url", pageBackgroundImgDataSrc);
14
- pageBackgroundImgDataSrc = "url('" + pageBackgroundImgDataSrc + "')";
15
- this.pageBackground.style.setProperty("--engrid__page-backgroundImage_url", pageBackgroundImgDataSrc);
16
- }
17
- else if (this.pageBackground && pageBackgroundImgSrc) {
18
- if (ENGrid.debug)
19
- console.log("A background image set in the page was found with a src value, setting it as --engrid__page-backgroundImage_url", pageBackgroundImgSrc);
20
- pageBackgroundImgSrc = "url('" + pageBackgroundImgSrc + "')";
21
- this.pageBackground.style.setProperty("--engrid__page-backgroundImage_url", pageBackgroundImgSrc);
22
- }
23
- else if (pageBackgroundImg) {
24
- if (ENGrid.debug)
25
- console.log("A background image set in the page was found but without a data-src or src value, no action taken", pageBackgroundImg);
26
- }
27
- else {
28
- if (ENGrid.debug)
29
- console.log("A background image set in the page was not found, any default image set in the theme on --engrid__page-backgroundImage_url will be used");
30
- }
6
+ this.mutationObserver = null;
7
+ this.logger = new EngridLogger("PageBackground", "lightblue", "darkblue", "🖼️");
8
+ if (!this.pageBackground) {
9
+ this.logger.log("A background image set in the page was not found, any default image set in the theme on --engrid__page-backgroundImage_url will be used");
10
+ return;
11
+ }
12
+ this.initializeBackgroundImage();
13
+ this.setDataAttributes();
14
+ this.processAttributionPositioning();
15
+ this.setupMutationObserver();
16
+ }
17
+ /**
18
+ * Initialize background image by finding and setting CSS custom property
19
+ */
20
+ initializeBackgroundImage() {
21
+ if (!this.pageBackground)
22
+ return;
23
+ const pageBackgroundImg = this.pageBackground.querySelector("img");
24
+ if (!pageBackgroundImg) {
25
+ this.logger.log("A background image set in the page was not found, any default image set in the theme on --engrid__page-backgroundImage_url will be used");
26
+ return;
27
+ }
28
+ const dataSrc = pageBackgroundImg.getAttribute("data-src");
29
+ const src = pageBackgroundImg.src;
30
+ if (dataSrc) {
31
+ this.setBackgroundImageUrl(dataSrc, "data-src");
32
+ }
33
+ else if (src) {
34
+ this.setBackgroundImageUrl(src, "src");
31
35
  }
32
36
  else {
33
- if (ENGrid.debug)
34
- console.log("A background image set in the page was not found, any default image set in the theme on --engrid__page-backgroundImage_url will be used");
37
+ this.logger.log("A background image set in the page was found but without a data-src or src value, no action taken", pageBackgroundImg);
38
+ }
39
+ }
40
+ /**
41
+ * Set the background image URL as a CSS custom property
42
+ */
43
+ setBackgroundImageUrl(imageUrl, sourceType) {
44
+ if (!this.pageBackground || !imageUrl)
45
+ return;
46
+ try {
47
+ const cssUrl = `url('${imageUrl}')`;
48
+ this.pageBackground.style.setProperty("--engrid__page-backgroundImage_url", cssUrl);
49
+ this.logger.log(`A background image set in the page was found with a ${sourceType} value, setting it as --engrid__page-backgroundImage_url`, imageUrl);
50
+ }
51
+ catch (error) {
52
+ this.logger.error("Error setting background image URL:", error);
53
+ }
54
+ }
55
+ /**
56
+ * Processes attribution positioning for background images by moving positioning classes
57
+ * and data attributes from images to their parent column containers.
58
+ *
59
+ * This function handles two attribution patterns:
60
+ * 1. Class-based: <img class="attribution-bottomright" src="...">
61
+ * 2. Data attribute-based: <img data-background-position="bottomright" src="...">
62
+ *
63
+ * Examples:
64
+ *
65
+ * Class-based attribution:
66
+ * <img class="attribution-bottomright" src="background.jpg">
67
+ * → Moves "attribution-bottomright" class to parent .en__component--column
68
+ *
69
+ * Data attribute-based attribution:
70
+ * <img data-background-position="top" src="background.jpg">
71
+ * → Converts to "attribution-top" class and moves to parent .en__component--column
72
+ *
73
+ * Supported positioning values:
74
+ * - center
75
+ * - top, topcenter (these result in the same positioning)
76
+ * - right, rightcenter (these result in the same positioning)
77
+ * - bottom, bottomcenter (these result in the same positioning)
78
+ * - left, leftcenter (these result in the same positioning)
79
+ * - topright
80
+ * - bottomright
81
+ * - bottomleft
82
+ * - topleft
83
+ */
84
+ processAttributionPositioning() {
85
+ if (!this.pageBackground) {
86
+ this.logger.log("No background section found for attribution positioning processing");
87
+ return;
88
+ }
89
+ this.logger.log("Processing attribution positioning for background section:", this.pageBackground);
90
+ // Define all supported attribution positioning classes
91
+ const allowedClasses = [
92
+ "attribution-center",
93
+ "attribution-bottom",
94
+ "attribution-bottomcenter",
95
+ "attribution-bottomright",
96
+ "attribution-bottomleft",
97
+ "attribution-top",
98
+ "attribution-topcenter",
99
+ "attribution-topright",
100
+ "attribution-topleft",
101
+ "attribution-left",
102
+ "attribution-leftcenter",
103
+ "attribution-right",
104
+ "attribution-rightcenter",
105
+ ];
106
+ try {
107
+ // Find all images in the background section (after any DOM transformations)
108
+ const images = this.pageBackground.querySelectorAll("img");
109
+ this.logger.log("Found images in background section:", images.length);
110
+ images.forEach((img) => {
111
+ this.processImageAttribution(img, allowedClasses);
112
+ });
113
+ }
114
+ catch (error) {
115
+ this.logger.error("Error processing attribution positioning:", error);
116
+ }
117
+ }
118
+ /**
119
+ * Process attribution for a single image
120
+ */
121
+ processImageAttribution(img, allowedClasses) {
122
+ // Pattern 1: Check for class-based attribution positioning
123
+ // Example: <img class="attribution-bottomright" src="...">
124
+ const matchedClass = allowedClasses.find((cls) => img.classList.contains(cls));
125
+ // Pattern 2: Check for data attribute-based attribution positioning
126
+ // Example: <img data-background-position="bottomright" src="...">
127
+ const dataPosition = img.getAttribute("data-background-position");
128
+ if (matchedClass) {
129
+ this.handleClassBasedAttribution(img, matchedClass);
130
+ }
131
+ else if (dataPosition) {
132
+ this.handleDataAttributeAttribution(img, dataPosition);
133
+ }
134
+ }
135
+ /**
136
+ * Handle class-based attribution positioning
137
+ */
138
+ handleClassBasedAttribution(img, matchedClass) {
139
+ this.logger.log("Found attribution class on image:", matchedClass, img);
140
+ const parentDiv = img.closest(".en__component--column");
141
+ if (parentDiv) {
142
+ // Move the class from image to parent column
143
+ img.classList.remove(matchedClass);
144
+ parentDiv.classList.add(matchedClass);
145
+ this.logger.log("Moved attribution class from image to parent column:", matchedClass, parentDiv);
146
+ }
147
+ else {
148
+ this.logger.log("No parent .en__component--column found for image:", img);
149
+ }
150
+ }
151
+ /**
152
+ * Handle data attribute-based attribution positioning
153
+ */
154
+ handleDataAttributeAttribution(img, dataPosition) {
155
+ // Convert data attribute value to attribution class format
156
+ const attributionClass = `attribution-${dataPosition}`;
157
+ this.logger.log("Found data-background-position on image:", dataPosition, "->", attributionClass, img);
158
+ const parentDiv = img.closest(".en__component--column");
159
+ if (parentDiv) {
160
+ // Remove data attribute from image and add class to parent column
161
+ img.removeAttribute("data-background-position");
162
+ parentDiv.classList.add(attributionClass);
163
+ this.logger.log("Moved data-background-position from image to parent column as class:", attributionClass, parentDiv);
164
+ }
165
+ else {
166
+ this.logger.log("No parent .en__component--column found for image:", img);
167
+ }
168
+ }
169
+ setupMutationObserver() {
170
+ if (!this.pageBackground || !window.MutationObserver) {
171
+ if (!window.MutationObserver) {
172
+ this.logger.log("MutationObserver not supported in this browser");
173
+ }
174
+ return;
175
+ }
176
+ try {
177
+ this.mutationObserver = new MutationObserver((mutations) => {
178
+ let shouldReprocess = false;
179
+ mutations.forEach((mutation) => {
180
+ // Check if nodes were added or attributes changed
181
+ if (mutation.type === "childList" || mutation.type === "attributes") {
182
+ shouldReprocess = true;
183
+ }
184
+ });
185
+ if (shouldReprocess) {
186
+ this.logger.log("DOM changes detected in background section, reprocessing attribution classes");
187
+ // Use a small delay to ensure all changes are complete
188
+ setTimeout(() => {
189
+ this.processAttributionPositioning();
190
+ }, 100);
191
+ }
192
+ });
193
+ // Start observing the background section
194
+ this.mutationObserver.observe(this.pageBackground, {
195
+ childList: true,
196
+ subtree: true,
197
+ attributes: true,
198
+ attributeFilter: ["class"],
199
+ });
200
+ this.logger.log("MutationObserver set up for background section");
201
+ }
202
+ catch (error) {
203
+ this.logger.error("Error setting up MutationObserver:", error);
204
+ }
205
+ }
206
+ // Public method to manually trigger reprocessing
207
+ reprocessAttributionPositioning() {
208
+ this.logger.log("Manually reprocessing attribution positioning");
209
+ this.processAttributionPositioning();
210
+ }
211
+ /**
212
+ * Clean up resources and observers
213
+ */
214
+ destroy() {
215
+ if (this.mutationObserver) {
216
+ this.mutationObserver.disconnect();
217
+ this.mutationObserver = null;
218
+ this.logger.log("MutationObserver disconnected");
35
219
  }
36
- this.setDataAttributes();
37
220
  }
38
221
  setDataAttributes() {
39
- if (this.hasVideoBackground())
222
+ if (this.hasVideoBackground()) {
40
223
  return ENGrid.setBodyData("page-background", "video");
41
- if (this.hasImageBackground())
224
+ }
225
+ if (this.hasImageBackground()) {
42
226
  return ENGrid.setBodyData("page-background", "image");
227
+ }
43
228
  return ENGrid.setBodyData("page-background", "empty");
44
229
  }
45
230
  hasVideoBackground() {
46
- if (this.pageBackground) {
47
- return !!this.pageBackground.querySelector("video");
231
+ if (!this.pageBackground) {
232
+ return false;
48
233
  }
234
+ return !!this.pageBackground.querySelector("video");
49
235
  }
50
236
  hasImageBackground() {
51
- if (this.pageBackground) {
52
- return (!this.hasVideoBackground() && !!this.pageBackground.querySelector("img"));
237
+ if (!this.pageBackground) {
238
+ return false;
53
239
  }
240
+ return (!this.hasVideoBackground() && !!this.pageBackground.querySelector("img"));
54
241
  }
55
242
  }
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const AppVersion = "0.22.10";
1
+ export declare const AppVersion = "0.22.11";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const AppVersion = "0.22.10";
1
+ export const AppVersion = "0.22.11";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@4site/engrid-scripts",
3
- "version": "0.22.10",
3
+ "version": "0.22.11",
4
4
  "description": "Scripts for the ENGRID Project",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -25,7 +25,7 @@
25
25
  "strongly-typed-events": "^2.0.9"
26
26
  },
27
27
  "homepage": "https://github.com/4site-interactive-studios/engrid#readme",
28
- "gitHead": "c005c8d8cf69b549193e053ed270a5a04ffe57af",
28
+ "gitHead": "ca99b189c78dbe2123d662fe1335063f3bddb8f1",
29
29
  "devDependencies": {
30
30
  "nodemon": "^2.0.20"
31
31
  }