notify-me-wl 1.0.1 → 1.2.0
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/README.md +206 -65
- package/index.html +3 -3
- package/index.js +49 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
### Coming Soon/Notify Me Widget
|
|
2
2
|
|
|
3
|
-
This widget allows users to
|
|
3
|
+
This JavaScript widget allows users to register their interest in a product that is either "coming soon" or "out of stock". Depending on the `data-type` attribute provided, the widget will display appropriate messages and functionality.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
- Integration with an external Wishlist API to handle form submissions
|
|
5
|
+
#### Features:
|
|
6
|
+
- Dynamically display a form to collect user information (email, mobile, first name, last name).
|
|
7
|
+
- Adjust form and button text based on the widget type (`notify-me` or `coming-soon`).
|
|
8
|
+
- Submit user data to a specified API endpoint with email or mobile as a path parameter and appropriate query parameters.
|
|
10
9
|
|
|
11
10
|
### Installation
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
Add the following script to your HTML to include the widget:
|
|
14
13
|
|
|
15
14
|
```html
|
|
16
15
|
<script src="https://cdn.jsdelivr.net/npm/notify-me-wl/index.js"></script>
|
|
@@ -18,73 +17,60 @@ Include the widget script in your HTML file:
|
|
|
18
17
|
|
|
19
18
|
### Usage
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
Add a button to your HTML where you want the widget to appear. The button should have an `id` of `popup-open`, a `data-fields` attribute with the fields you want to include in the form (as a JSON string), and a `data-type` attribute to specify the widget type (`notify-me` or `coming-soon`).
|
|
22
21
|
|
|
23
22
|
```html
|
|
24
|
-
<div id="
|
|
25
|
-
|
|
26
|
-
</div>
|
|
23
|
+
<div id="notification-widget"></div>
|
|
24
|
+
<button id="popup-open" data-fields='["email", "mobile", "firstName", "lastName"]' data-type="notify-me">Open Popup</button>
|
|
27
25
|
```
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
### Customization
|
|
32
|
-
|
|
33
|
-
#### Fields
|
|
34
|
-
|
|
35
|
-
The `data-fields` attribute on the button determines which fields will be included in the form. Possible values include:
|
|
27
|
+
### Configuration
|
|
36
28
|
|
|
37
|
-
- `email`
|
|
38
|
-
- `
|
|
39
|
-
- `firstName`
|
|
40
|
-
- `lastName`
|
|
29
|
+
- `data-fields`: A JSON array specifying the fields to include in the form. Possible values are `"email"`, `"mobile"`, `"firstName"`, and `"lastName"`.
|
|
30
|
+
- `data-type`: Specifies the type of the widget. Possible values are `"notify-me"` and `"coming-soon"`.
|
|
41
31
|
|
|
42
|
-
Example
|
|
32
|
+
### Example
|
|
43
33
|
|
|
44
34
|
```html
|
|
45
|
-
<
|
|
46
|
-
|
|
35
|
+
<div id="notification-widget"></div>
|
|
36
|
+
<button id="popup-open" data-fields='["email", "mobile"]' data-type="notify-me">Open Popup</button>
|
|
47
37
|
|
|
48
|
-
|
|
38
|
+
<script>
|
|
39
|
+
// The script provided will be included here
|
|
40
|
+
</script>
|
|
41
|
+
```
|
|
49
42
|
|
|
50
|
-
|
|
43
|
+
### How It Works
|
|
51
44
|
|
|
52
|
-
|
|
45
|
+
1. **Initialization**: The script listens for the `DOMContentLoaded` event to initialize the widget.
|
|
46
|
+
2. **Styles Injection**: It injects necessary styles for the modal and form elements.
|
|
47
|
+
3. **Modal Creation**: Creates the modal structure and appends it to the `notification-widget` div.
|
|
48
|
+
4. **Dynamic Content**: Based on the `data-type`, it sets the appropriate messages and button text.
|
|
49
|
+
5. **Form Submission**: Collects form data and submits it to the API with the email or mobile number as a path parameter. If a mobile number is provided, it also appends `isMobile=true` to the query string.
|
|
53
50
|
|
|
54
|
-
|
|
51
|
+
### API Request Example
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
For email:
|
|
54
|
+
```
|
|
55
|
+
https://api.au-aws.thewishlist.io/services/wsservice/api/wishlist/items/customerInterest/{email}
|
|
58
56
|
```
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
{
|
|
64
|
-
"productRef": 6786188247105,
|
|
65
|
-
"variantRef": 1,
|
|
66
|
-
"email": "example@example.com",
|
|
67
|
-
"mobile": "1234567890",
|
|
68
|
-
"firstName": "John",
|
|
69
|
-
"lastName": "Doe",
|
|
70
|
-
"isMobile": true
|
|
71
|
-
}
|
|
58
|
+
For mobile:
|
|
59
|
+
```
|
|
60
|
+
https://api.au-aws.thewishlist.io/services/wsservice/api/wishlist/items/customerInterest/{mobile}?isMobile=true
|
|
72
61
|
```
|
|
73
62
|
|
|
74
|
-
###
|
|
63
|
+
### Full Script
|
|
75
64
|
|
|
76
|
-
|
|
65
|
+
```javascript
|
|
66
|
+
const ACCESS_TOKEN = "123"; // // Replace `ACCESS_TOKEN` with your actual access token to authenticate API requests.
|
|
77
67
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
<title>Notify Me Widget</title>
|
|
85
|
-
<style>
|
|
86
|
-
/* Custom styles for the button and popup form */
|
|
87
|
-
.notify-me-btn {
|
|
68
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
69
|
+
const wrapper = document.getElementById("notification-widget");
|
|
70
|
+
if (!wrapper) return;
|
|
71
|
+
|
|
72
|
+
const styles = `
|
|
73
|
+
.notification-btn {
|
|
88
74
|
background-color: #fff;
|
|
89
75
|
border: 1px solid black;
|
|
90
76
|
color: black;
|
|
@@ -196,15 +182,170 @@ Here is a complete example of an HTML file that includes the Notify Me Widget:
|
|
|
196
182
|
border-top: var(--size) solid black;
|
|
197
183
|
top: 55%;
|
|
198
184
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
185
|
+
`;
|
|
186
|
+
|
|
187
|
+
const styleSheet = document.createElement("style");
|
|
188
|
+
styleSheet.type = "text/css";
|
|
189
|
+
styleSheet.innerText = styles;
|
|
190
|
+
document.head.appendChild(styleSheet);
|
|
191
|
+
|
|
192
|
+
const overlay = document.createElement("div");
|
|
193
|
+
overlay.innerHTML = `
|
|
194
|
+
<div id="popup-body" class="overlay">
|
|
195
|
+
<div id="popup-wrapper">
|
|
196
|
+
<h3 id="popup-title"></h3>
|
|
197
|
+
<span id="popup-close">×</span>
|
|
198
|
+
<div id="popup-text"></div>
|
|
199
|
+
<form id="popup-form">
|
|
200
|
+
<div class="custom-select">
|
|
201
|
+
<select name="select-size" required>
|
|
202
|
+
</select>
|
|
203
|
+
</div>
|
|
204
|
+
</form>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
`;
|
|
208
|
+
|
|
209
|
+
wrapper.appendChild(overlay);
|
|
210
|
+
|
|
211
|
+
const popupBody = document.getElementById("popup-body");
|
|
212
|
+
const popupClose = document.getElementById("popup-close");
|
|
213
|
+
const popupOpenButton = document.getElementById("popup-open");
|
|
214
|
+
const popupTitle = document.getElementById("popup-title");
|
|
215
|
+
const popupText = document.getElementById("popup-text");
|
|
216
|
+
const sizeSelect = document.querySelector("select[name='select-size']");
|
|
217
|
+
const form = overlay.querySelector("#popup-form");
|
|
218
|
+
|
|
219
|
+
if (!popupBody || !popupClose || !popupOpenButton || !popupTitle || !sizeSelect) return;
|
|
220
|
+
|
|
221
|
+
const fields = JSON.parse(popupOpenButton.getAttribute("data-fields") || '["email"]');
|
|
222
|
+
const type = popupOpenButton.getAttribute("data-type") || "notify-me";
|
|
223
|
+
|
|
224
|
+
const typeConfig = {
|
|
225
|
+
"notify-me": {
|
|
226
|
+
text: "Register to receive a notification as soon as this item is back in stock",
|
|
227
|
+
buttonText: "Notify me",
|
|
228
|
+
},
|
|
229
|
+
"coming-soon": {
|
|
230
|
+
text: "Register your interest to hear more about this item",
|
|
231
|
+
buttonText: "Register Interest",
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
// Get product data from Shopify's global variable
|
|
236
|
+
const productData = window.Shopify?.product || {
|
|
237
|
+
id: 6786188247105,
|
|
238
|
+
title: "THE ATG SCULPT FLARES TALL",
|
|
239
|
+
product_option_value: {
|
|
240
|
+
name: "BUTTER BLACK",
|
|
241
|
+
},
|
|
242
|
+
variants: [
|
|
243
|
+
{ id: 1, title: "S" },
|
|
244
|
+
{ id: 2, title: "M" },
|
|
245
|
+
{ id: 3, title: "L" },
|
|
246
|
+
{ id: 4, title: "XL" },
|
|
247
|
+
],
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
popupTitle.innerHTML = productData.title + "<br/>" + productData.product_option_value.name;
|
|
251
|
+
popupText.innerText = typeConfig[type].text;
|
|
252
|
+
productData.variants.forEach((variant) => {
|
|
253
|
+
const option = document.createElement("option");
|
|
254
|
+
option.value = variant.title;
|
|
255
|
+
option.textContent = variant.title;
|
|
256
|
+
sizeSelect.appendChild(option);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
const fieldMap = {
|
|
260
|
+
email: `<input name="email" placeholder="Email" type="email" required />`,
|
|
261
|
+
mobile: `<input name="mobile" placeholder="Mobile"
|
|
262
|
+
|
|
263
|
+
type="tel" required />`,
|
|
264
|
+
firstName: `<input name="firstName" placeholder="First name" type="text" required />`,
|
|
265
|
+
lastName: `<input name="lastName" placeholder="Last name" type="text" required />`,
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
fields.forEach((field) => {
|
|
269
|
+
if (fieldMap[field]) {
|
|
270
|
+
form.insertAdjacentHTML("beforeend", fieldMap[field]);
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
form.insertAdjacentHTML("beforeend", `<button type="submit">${typeConfig[type].buttonText}</button>`);
|
|
274
|
+
|
|
275
|
+
function showPopup() {
|
|
276
|
+
popupBody.style.visibility = "visible";
|
|
277
|
+
popupBody.style.opacity = 1;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function hidePopup() {
|
|
281
|
+
popupBody.style.visibility = "hidden";
|
|
282
|
+
popupBody.style.opacity = 0;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
popupOpenButton.addEventListener("click", showPopup);
|
|
286
|
+
popupClose.addEventListener("click", hidePopup);
|
|
287
|
+
|
|
288
|
+
if (form) {
|
|
289
|
+
form.addEventListener("submit", function (event) {
|
|
290
|
+
event.preventDefault();
|
|
291
|
+
|
|
292
|
+
const selectedSize = sizeSelect.value;
|
|
293
|
+
const selectedVariant = productData.variants.find((variant) => variant.title === selectedSize);
|
|
294
|
+
|
|
295
|
+
if (selectedVariant) {
|
|
296
|
+
const formData = {
|
|
297
|
+
productRef: productData.id,
|
|
298
|
+
variantRef: selectedVariant.id,
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
let contactInfo = "";
|
|
302
|
+
if (fields.includes("email")) {
|
|
303
|
+
formData.email = form.querySelector("input[name='email']").value;
|
|
304
|
+
contactInfo = formData.email;
|
|
305
|
+
}
|
|
306
|
+
if (fields.includes("firstName")) {
|
|
307
|
+
formData.firstName = form.querySelector("input[name='firstName']").value;
|
|
308
|
+
}
|
|
309
|
+
if (fields.includes("lastName")) {
|
|
310
|
+
formData.lastName = form.querySelector("input[name='lastName']").value;
|
|
311
|
+
}
|
|
312
|
+
if (fields.includes("mobile")) {
|
|
313
|
+
formData.mobile = form.querySelector("input[name='mobile']").value;
|
|
314
|
+
formData.isMobile = true;
|
|
315
|
+
contactInfo = formData.mobile;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
let url = `https://api.au-aws.thewishlist.io/services/wsservice/api/wishlist/items/customerInterest/${contactInfo}?notifyMe=true`;
|
|
319
|
+
if (formData.isMobile) {
|
|
320
|
+
url += "&isMobile=true";
|
|
321
|
+
}
|
|
205
322
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
323
|
+
fetch(url, {
|
|
324
|
+
method: "POST",
|
|
325
|
+
headers: {
|
|
326
|
+
"Content-Type": "application/json",
|
|
327
|
+
Authorization: ACCESS_TOKEN,
|
|
328
|
+
},
|
|
329
|
+
body: JSON.stringify(formData),
|
|
330
|
+
})
|
|
331
|
+
.then((response) => {
|
|
332
|
+
if (response.ok) {
|
|
333
|
+
alert("Form submitted");
|
|
334
|
+
hidePopup();
|
|
335
|
+
} else {
|
|
336
|
+
alert("Form submission failed");
|
|
337
|
+
}
|
|
338
|
+
})
|
|
339
|
+
.catch((error) => {
|
|
340
|
+
console.error("Error submitting form:", error);
|
|
341
|
+
alert("Form submission failed");
|
|
342
|
+
});
|
|
343
|
+
} else {
|
|
344
|
+
alert("Selected variant not found");
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
});
|
|
209
349
|
```
|
|
210
350
|
|
|
351
|
+
Replace `ACCESS_TOKEN` with your actual access token to authenticate API requests.
|
package/index.html
CHANGED
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
</style>
|
|
14
14
|
</head>
|
|
15
15
|
<body>
|
|
16
|
-
<div id="
|
|
17
|
-
<button id="popup-open" class="notify-me
|
|
18
|
-
|
|
16
|
+
<div id="notification-widget">
|
|
17
|
+
<button id="popup-open" class="notification-btn" type="button" data-type="notify-me" data-fields='["email", "mobile", "firstName", "lastName"]'>Notify Me - Join Waitlist</button>
|
|
18
|
+
</div>
|
|
19
19
|
</body>
|
|
20
20
|
<script src="/index.js"></script>
|
|
21
21
|
</html>
|
package/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// Access token for the API
|
|
2
|
-
const ACCESS_TOKEN = "123";
|
|
2
|
+
const ACCESS_TOKEN = "123"; // Replace `ACCESS_TOKEN` with your actual access token to authenticate API requests.
|
|
3
3
|
|
|
4
4
|
document.addEventListener("DOMContentLoaded", function () {
|
|
5
|
-
const wrapper = document.getElementById("
|
|
5
|
+
const wrapper = document.getElementById("notification-widget");
|
|
6
6
|
if (!wrapper) return;
|
|
7
7
|
|
|
8
8
|
// Define and apply styles for the popup and button
|
|
9
9
|
const styles = `
|
|
10
|
-
.
|
|
10
|
+
.notification-btn {
|
|
11
11
|
background-color: #fff;
|
|
12
12
|
border: 1px solid black;
|
|
13
13
|
color: black;
|
|
@@ -133,7 +133,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|
|
133
133
|
<div id="popup-wrapper">
|
|
134
134
|
<h3 id="popup-title"></h3>
|
|
135
135
|
<span id="popup-close">×</span>
|
|
136
|
-
<div id="popup-text"
|
|
136
|
+
<div id="popup-text"></div>
|
|
137
137
|
<form id="popup-form">
|
|
138
138
|
<div class="custom-select">
|
|
139
139
|
<select name="select-size" required>
|
|
@@ -150,13 +150,25 @@ document.addEventListener("DOMContentLoaded", function () {
|
|
|
150
150
|
const popupClose = document.getElementById("popup-close");
|
|
151
151
|
const popupOpenButton = document.getElementById("popup-open");
|
|
152
152
|
const popupTitle = document.getElementById("popup-title");
|
|
153
|
+
const popupText = document.getElementById("popup-text");
|
|
153
154
|
const sizeSelect = document.querySelector("select[name='select-size']");
|
|
154
155
|
const form = overlay.querySelector("#popup-form");
|
|
155
156
|
|
|
156
157
|
if (!popupBody || !popupClose || !popupOpenButton || !popupTitle || !sizeSelect) return;
|
|
157
158
|
|
|
158
|
-
// Parse fields to be included in the form from data attribute
|
|
159
|
+
// Parse fields and type to be included in the form from data attribute
|
|
159
160
|
const fields = JSON.parse(popupOpenButton.getAttribute("data-fields") || '["email"]');
|
|
161
|
+
const type = popupOpenButton.getAttribute("data-type") || "notify-me";
|
|
162
|
+
const typeConfig = {
|
|
163
|
+
"notify-me": {
|
|
164
|
+
text: "Register to receive a notification as soon as this item is back in stock",
|
|
165
|
+
buttonText: "Notify me",
|
|
166
|
+
},
|
|
167
|
+
"coming-soon": {
|
|
168
|
+
text: "Register your interest to hear more about this item",
|
|
169
|
+
buttonText: "Register Interest",
|
|
170
|
+
},
|
|
171
|
+
};
|
|
160
172
|
|
|
161
173
|
// Get product data from Shopify's global variable
|
|
162
174
|
const productData = window.Shopify?.product || {
|
|
@@ -183,6 +195,15 @@ document.addEventListener("DOMContentLoaded", function () {
|
|
|
183
195
|
});
|
|
184
196
|
|
|
185
197
|
// Map for form fields
|
|
198
|
+
popupTitle.innerHTML = productData.title + "<br/>" + productData.product_option_value.name;
|
|
199
|
+
popupText.innerText = typeConfig[type].text;
|
|
200
|
+
productData.variants.forEach((variant) => {
|
|
201
|
+
const option = document.createElement("option");
|
|
202
|
+
option.value = variant.title;
|
|
203
|
+
option.textContent = variant.title;
|
|
204
|
+
sizeSelect.appendChild(option);
|
|
205
|
+
});
|
|
206
|
+
|
|
186
207
|
const fieldMap = {
|
|
187
208
|
email: `<input name="email" placeholder="Email" type="email" required />`,
|
|
188
209
|
mobile: `<input name="mobile" placeholder="Mobile" type="tel" required />`,
|
|
@@ -196,7 +217,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|
|
196
217
|
form.insertAdjacentHTML("beforeend", fieldMap[field]);
|
|
197
218
|
}
|
|
198
219
|
});
|
|
199
|
-
form.insertAdjacentHTML("beforeend", `<button type="submit"
|
|
220
|
+
form.insertAdjacentHTML("beforeend", `<button type="submit">${typeConfig[type].buttonText}</button>`);
|
|
200
221
|
|
|
201
222
|
// Show/hide the popup
|
|
202
223
|
function showPopup() {
|
|
@@ -224,23 +245,31 @@ document.addEventListener("DOMContentLoaded", function () {
|
|
|
224
245
|
const formData = {
|
|
225
246
|
productRef: productData.id,
|
|
226
247
|
variantRef: selectedVariant.id,
|
|
227
|
-
|
|
248
|
+
};
|
|
228
249
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
250
|
+
let contactInfo = "";
|
|
251
|
+
if (fields.includes("email")) {
|
|
252
|
+
formData.email = form.querySelector("input[name='email']").value;
|
|
253
|
+
contactInfo = formData.email;
|
|
254
|
+
}
|
|
255
|
+
if (fields.includes("firstName")) {
|
|
256
|
+
formData.firstName = form.querySelector("input[name='firstName']").value;
|
|
257
|
+
}
|
|
258
|
+
if (fields.includes("lastName")) {
|
|
259
|
+
formData.lastName = form.querySelector("input[name='lastName']").value;
|
|
260
|
+
}
|
|
261
|
+
if (fields.includes("mobile")) {
|
|
262
|
+
formData.mobile = form.querySelector("input[name='mobile']").value;
|
|
240
263
|
formData.isMobile = true;
|
|
241
|
-
|
|
264
|
+
contactInfo = formData.mobile;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
let url = `https://api.au-aws.thewishlist.io/services/wsservice/api/wishlist/items/customerInterest/${contactInfo}`;
|
|
268
|
+
if (formData.isMobile) {
|
|
269
|
+
url += "?isMobile=true";
|
|
270
|
+
}
|
|
242
271
|
|
|
243
|
-
fetch(
|
|
272
|
+
fetch(url, {
|
|
244
273
|
method: "POST",
|
|
245
274
|
headers: {
|
|
246
275
|
"Content-Type": "application/json",
|