@4site/engrid-scripts 0.28.3 → 0.28.4
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/remember-me.d.ts +5 -0
- package/dist/remember-me.js +136 -11
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/dist/remember-me.d.ts
CHANGED
|
@@ -42,7 +42,12 @@ export declare class RememberMe {
|
|
|
42
42
|
});
|
|
43
43
|
private updateFieldData;
|
|
44
44
|
private insertClearRememberMeLink;
|
|
45
|
+
private escapeHtml;
|
|
46
|
+
private buildClearLabelMarkup;
|
|
47
|
+
private getUsernameFromFieldData;
|
|
48
|
+
private getClearLabelPlainText;
|
|
45
49
|
private getElementByFirstSelector;
|
|
50
|
+
private placeOnRightSide;
|
|
46
51
|
private insertRememberMeOptin;
|
|
47
52
|
private useRemote;
|
|
48
53
|
private createIframe;
|
package/dist/remember-me.js
CHANGED
|
@@ -165,16 +165,26 @@ export class RememberMe {
|
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
167
|
insertClearRememberMeLink() {
|
|
168
|
+
var _a;
|
|
168
169
|
let clearRememberMeField = document.getElementById("clear-autofill-data");
|
|
170
|
+
const { html, hasInnerLink } = this.buildClearLabelMarkup();
|
|
169
171
|
if (!clearRememberMeField) {
|
|
170
|
-
clearRememberMeField = document.createElement("a");
|
|
172
|
+
clearRememberMeField = document.createElement(hasInnerLink ? "span" : "a");
|
|
171
173
|
clearRememberMeField.setAttribute("id", "clear-autofill-data");
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
174
|
+
if (hasInnerLink) {
|
|
175
|
+
clearRememberMeField.classList.add("clear-autofill-data-wrapper");
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
clearRememberMeField.classList.add("label-tooltip");
|
|
179
|
+
clearRememberMeField.setAttribute("style", "cursor: pointer;");
|
|
180
|
+
}
|
|
181
|
+
clearRememberMeField.innerHTML = html;
|
|
175
182
|
const targetField = this.getElementByFirstSelector(this.fieldClearSelectorTarget);
|
|
176
183
|
if (targetField) {
|
|
177
|
-
if (this.fieldClearSelectorTargetLocation === "
|
|
184
|
+
if (this.fieldClearSelectorTargetLocation === "rightSide") {
|
|
185
|
+
this.placeOnRightSide(targetField, clearRememberMeField);
|
|
186
|
+
}
|
|
187
|
+
else if (this.fieldClearSelectorTargetLocation === "after") {
|
|
178
188
|
targetField.appendChild(clearRememberMeField);
|
|
179
189
|
}
|
|
180
190
|
else {
|
|
@@ -182,7 +192,10 @@ export class RememberMe {
|
|
|
182
192
|
}
|
|
183
193
|
}
|
|
184
194
|
}
|
|
185
|
-
|
|
195
|
+
const clickTarget = hasInnerLink
|
|
196
|
+
? (_a = clearRememberMeField.querySelector("#clear-autofill-data-link")) !== null && _a !== void 0 ? _a : clearRememberMeField
|
|
197
|
+
: clearRememberMeField;
|
|
198
|
+
const onClear = (e) => {
|
|
186
199
|
e.preventDefault();
|
|
187
200
|
this.clearFields(["supporter.country" /*, 'supporter.emailAddress'*/]);
|
|
188
201
|
if (this.useRemote()) {
|
|
@@ -201,10 +214,54 @@ export class RememberMe {
|
|
|
201
214
|
this.rememberMeOptIn = false;
|
|
202
215
|
this._events.dispatchClear();
|
|
203
216
|
window.dispatchEvent(new CustomEvent("RememberMe_Cleared"));
|
|
204
|
-
}
|
|
217
|
+
};
|
|
218
|
+
clickTarget.addEventListener("click", onClear);
|
|
205
219
|
this._events.dispatchLoad(true);
|
|
206
220
|
window.dispatchEvent(new CustomEvent("RememberMe_Loaded", { detail: { withData: true } }));
|
|
207
221
|
}
|
|
222
|
+
escapeHtml(value) {
|
|
223
|
+
const map = {
|
|
224
|
+
"&": "&",
|
|
225
|
+
"<": "<",
|
|
226
|
+
">": ">",
|
|
227
|
+
'"': """,
|
|
228
|
+
"'": "'",
|
|
229
|
+
};
|
|
230
|
+
return value.replace(/[&<>"']/g, (c) => map[c]);
|
|
231
|
+
}
|
|
232
|
+
buildClearLabelMarkup() {
|
|
233
|
+
var _a;
|
|
234
|
+
const username = this.getUsernameFromFieldData();
|
|
235
|
+
const label = username
|
|
236
|
+
? this.fieldClearLabel.replace(/\$username/g, () => this.escapeHtml(username))
|
|
237
|
+
: this.fieldClearLabel.replace(/[^\S\r\n]?\$username/g, "");
|
|
238
|
+
// Only the first non-empty {...} segment becomes the clickable clear link.
|
|
239
|
+
// Any additional {...} segments remain as literal text (braces included),
|
|
240
|
+
// and empty {} braces are left as-is. When no non-empty braces are present,
|
|
241
|
+
// the entire element is clickable (legacy behaviour).
|
|
242
|
+
const match = label.match(/\{([^}]+)\}/);
|
|
243
|
+
if (!match) {
|
|
244
|
+
return { html: label, hasInnerLink: false };
|
|
245
|
+
}
|
|
246
|
+
const before = label.slice(0, match.index);
|
|
247
|
+
const linkText = match[1];
|
|
248
|
+
const after = label.slice(((_a = match.index) !== null && _a !== void 0 ? _a : 0) + match[0].length);
|
|
249
|
+
const html = before +
|
|
250
|
+
`<a id="clear-autofill-data-link" class="label-tooltip" style="cursor: pointer;">${linkText}</a>` +
|
|
251
|
+
after;
|
|
252
|
+
return { html, hasInnerLink: true };
|
|
253
|
+
}
|
|
254
|
+
getUsernameFromFieldData() {
|
|
255
|
+
const value = this.fieldData["supporter.firstName"];
|
|
256
|
+
return value ? value.trim() : "";
|
|
257
|
+
}
|
|
258
|
+
getClearLabelPlainText() {
|
|
259
|
+
const username = this.getUsernameFromFieldData();
|
|
260
|
+
const label = username
|
|
261
|
+
? this.fieldClearLabel.replace(/\$username/g, () => username)
|
|
262
|
+
: this.fieldClearLabel.replace(/[^\S\r\n]?\$username/g, "");
|
|
263
|
+
return label.replace(/\{([^}]*)\}/g, "$1");
|
|
264
|
+
}
|
|
208
265
|
getElementByFirstSelector(selectorsString) {
|
|
209
266
|
// iterate through the selectors until we find one that exists
|
|
210
267
|
let targetField = null;
|
|
@@ -217,13 +274,76 @@ export class RememberMe {
|
|
|
217
274
|
}
|
|
218
275
|
return targetField;
|
|
219
276
|
}
|
|
277
|
+
placeOnRightSide(targetField, elementToPlace) {
|
|
278
|
+
const wrapperClass = "rememberme-right-side-wrapper";
|
|
279
|
+
let wrapper;
|
|
280
|
+
if (targetField.parentElement &&
|
|
281
|
+
targetField.parentElement.classList.contains(wrapperClass)) {
|
|
282
|
+
wrapper = targetField.parentElement;
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
// Read the target's computed styles BEFORE moving it into the flex
|
|
286
|
+
// wrapper. Once inside a flex container, margin collapsing no longer
|
|
287
|
+
// applies and the reported values can change. We transfer the original
|
|
288
|
+
// margin-top to the wrapper itself so the block retains its vertical
|
|
289
|
+
// spacing in the document flow, and zero out the target's own margin-top
|
|
290
|
+
// so it doesn't double-apply inside the flex row.
|
|
291
|
+
const targetStyle = window.getComputedStyle(targetField);
|
|
292
|
+
const targetMarginTop = targetStyle.marginTop;
|
|
293
|
+
const targetMarginBottom = targetStyle.marginBottom;
|
|
294
|
+
wrapper = document.createElement("div");
|
|
295
|
+
wrapper.classList.add(wrapperClass);
|
|
296
|
+
wrapper.style.display = "flex";
|
|
297
|
+
wrapper.style.alignItems = "center";
|
|
298
|
+
wrapper.style.gap = "8px";
|
|
299
|
+
wrapper.style.flexWrap = "wrap";
|
|
300
|
+
// Transfer vertical margins from the target to the wrapper so the
|
|
301
|
+
// surrounding layout is unchanged after the DOM move.
|
|
302
|
+
wrapper.style.marginTop = targetMarginTop;
|
|
303
|
+
wrapper.style.marginBottom = targetMarginBottom;
|
|
304
|
+
if (targetField.parentNode) {
|
|
305
|
+
targetField.parentNode.insertBefore(wrapper, targetField);
|
|
306
|
+
}
|
|
307
|
+
// Zero out the target's own margin-top/-bottom now that the wrapper
|
|
308
|
+
// owns them, so they don't double-apply inside the flex row.
|
|
309
|
+
targetField.style.marginTop = "0px";
|
|
310
|
+
targetField.style.marginBottom = "0px";
|
|
311
|
+
wrapper.appendChild(targetField);
|
|
312
|
+
}
|
|
313
|
+
// Read padding-left AFTER the wrapper exists but before any alignment
|
|
314
|
+
// logic, so it reflects the current computed value.
|
|
315
|
+
const targetPaddingLeft = window.getComputedStyle(targetField).paddingLeft;
|
|
316
|
+
wrapper.appendChild(elementToPlace);
|
|
317
|
+
const applyAlignment = () => {
|
|
318
|
+
const wrapped = elementToPlace.offsetTop > targetField.offsetTop;
|
|
319
|
+
if (wrapped) {
|
|
320
|
+
// When wrapped below, left-align with the target's content area.
|
|
321
|
+
elementToPlace.style.marginTop = "0px";
|
|
322
|
+
elementToPlace.style.marginLeft = targetPaddingLeft;
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
// When side-by-side, both items are already vertically centred by the
|
|
326
|
+
// flex container — no extra margin-top needed on elementToPlace.
|
|
327
|
+
elementToPlace.style.marginTop = "0px";
|
|
328
|
+
elementToPlace.style.marginLeft = "0px";
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
// Defer the first alignment check to the next animation frame so the
|
|
332
|
+
// browser has had a chance to perform layout. Without this, offsetTop on
|
|
333
|
+
// both elements is still 0 (or stale) at call time.
|
|
334
|
+
requestAnimationFrame(applyAlignment);
|
|
335
|
+
if (typeof window.ResizeObserver === "function") {
|
|
336
|
+
const observer = new window.ResizeObserver(() => applyAlignment());
|
|
337
|
+
observer.observe(wrapper);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
220
340
|
insertRememberMeOptin() {
|
|
221
341
|
let rememberMeOptInField = document.getElementById("remember-me-opt-in");
|
|
222
342
|
if (!rememberMeOptInField) {
|
|
223
343
|
const rememberMeLabel = this.rememberMeLabel;
|
|
224
344
|
const rememberMeInfo = ENGrid.t("rememberMe.tooltip", {
|
|
225
345
|
label: rememberMeLabel,
|
|
226
|
-
clearLabel: this.
|
|
346
|
+
clearLabel: this.getClearLabelPlainText(),
|
|
227
347
|
});
|
|
228
348
|
const rememberMeOptInFieldChecked = this.rememberMeOptIn ? "checked" : "";
|
|
229
349
|
const rememberMeOptInField = document.createElement("div");
|
|
@@ -247,9 +367,14 @@ export class RememberMe {
|
|
|
247
367
|
`;
|
|
248
368
|
const targetField = this.getElementByFirstSelector(this.fieldOptInSelectorTarget);
|
|
249
369
|
if (targetField && targetField.parentNode) {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
370
|
+
if (this.fieldOptInSelectorTargetLocation === "rightSide") {
|
|
371
|
+
this.placeOnRightSide(targetField, rememberMeOptInField);
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
targetField.parentNode.insertBefore(rememberMeOptInField, this.fieldOptInSelectorTargetLocation == "before"
|
|
375
|
+
? targetField
|
|
376
|
+
: targetField.nextSibling);
|
|
377
|
+
}
|
|
253
378
|
const rememberMeCheckbox = document.getElementById("remember-me-checkbox");
|
|
254
379
|
if (rememberMeCheckbox) {
|
|
255
380
|
rememberMeCheckbox.addEventListener("change", () => {
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AppVersion = "0.28.
|
|
1
|
+
export declare const AppVersion = "0.28.4";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AppVersion = "0.28.
|
|
1
|
+
export const AppVersion = "0.28.4";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@4site/engrid-scripts",
|
|
3
|
-
"version": "0.28.
|
|
3
|
+
"version": "0.28.4",
|
|
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": "
|
|
28
|
+
"gitHead": "fb6e68d0a52142cba344b693972b38da7dcea795",
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"nodemon": "^2.0.20",
|
|
31
31
|
"typescript": "^4.9.5"
|