PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.83
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.83
51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 51.1.46 51.1.47 51.1.49 All 37 releases
king-addons / includes / extensions / Age_Gate / assets / script.js

script.js in King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder 51.1.83, at includes/extensions/Age_Gate/assets/script.js

447 lines 16.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 const payload = window.kingAddonsAgeGate;
3
4 if (!payload || !payload.enabled) {
5 return;
6 }
7
8 const root = ensureRoot();
9 const card = root.querySelector('.king-addons-age-gate__card');
10 const content = root.querySelector('.king-addons-age-gate__content');
11 const state = {
12 status: payload.status || '',
13 cookieDays: resolveCookieDays(payload),
14 };
15
16 applyDesign(root, card, payload);
17
18 const needsBlock = payload.behaviour && payload.behaviour.denyAction === 'block' && state.status === 'denied';
19
20 if (!payload.shouldRender && !needsBlock) {
21 return;
22 }
23
24 lockScroll();
25 showOverlay(root, payload);
26
27 if (payload.elementorTemplate) {
28 const templateWrapper = document.createElement('div');
29 templateWrapper.className = 'king-addons-age-gate__template';
30 templateWrapper.innerHTML = payload.elementorTemplate;
31 content.appendChild(templateWrapper);
32 }
33
34 if (needsBlock) {
35 renderBlocked(content, payload);
36 return;
37 }
38
39 if (payload.mode === 'dob' && payload.isPremium) {
40 renderDob(content, payload, state);
41 } else {
42 renderYesNo(content, payload, state);
43 }
44
45 /**
46 * Creates root container if not present.
47 */
48 function ensureRoot() {
49 let rootEl = document.getElementById('king-addons-age-gate');
50 if (!rootEl) {
51 rootEl = document.createElement('div');
52 rootEl.id = 'king-addons-age-gate';
53 rootEl.className = 'king-addons-age-gate';
54 rootEl.innerHTML = '<div class="king-addons-age-gate__overlay"></div><div class="king-addons-age-gate__card"><div class="king-addons-age-gate__content"></div></div>';
55 document.body.appendChild(rootEl);
56 }
57 return rootEl;
58 }
59
60 /**
61 * Applies design variables to the overlay.
62 */
63 function applyDesign(rootEl, cardEl, data) {
64 const design = data.design || {};
65 rootEl.style.setProperty('--ka-age-overlay', design.overlayColor || '#0d0d0d');
66 rootEl.style.setProperty('--ka-age-overlay-opacity', design.overlayOpacity ?? 0.7);
67 rootEl.style.setProperty('--ka-age-card-bg', design.cardBackground || '#ffffff');
68 rootEl.style.setProperty('--ka-age-card-width', (design.cardWidth || 520) + 'px');
69 rootEl.style.setProperty('--ka-age-text', design.textColor || '#111827');
70 rootEl.style.setProperty('--ka-age-title-size', (design.titleSize || 24) + 'px');
71 rootEl.style.setProperty('--ka-age-body-size', (design.bodySize || 16) + 'px');
72 rootEl.style.setProperty('--ka-age-title-weight', design.titleWeight || 700);
73 rootEl.style.setProperty('--ka-age-body-weight', design.bodyWeight || 400);
74 rootEl.style.setProperty('--ka-age-btn-yes-color', design.buttonYesColor || '#ffffff');
75 rootEl.style.setProperty('--ka-age-btn-yes-bg', design.buttonYesBg || '#10b981');
76 rootEl.style.setProperty('--ka-age-btn-no-color', design.buttonNoColor || '#ffffff');
77 rootEl.style.setProperty('--ka-age-btn-no-bg', design.buttonNoBg || '#ef4444');
78 rootEl.style.setProperty('--ka-age-btn-yes-hover-bg', design.buttonYesHoverBg || design.buttonYesBg || '#0f9c75');
79 rootEl.style.setProperty('--ka-age-btn-no-hover-bg', design.buttonNoHoverBg || design.buttonNoBg || '#d92d20');
80 rootEl.style.setProperty('--ka-age-btn-yes-hover-color', design.buttonYesHoverColor || design.buttonYesColor || '#ffffff');
81 rootEl.style.setProperty('--ka-age-btn-no-hover-color', design.buttonNoHoverColor || design.buttonNoColor || '#ffffff');
82
83 if (design.cardAlign === 'bottom') {
84 cardEl.classList.add('king-addons-age-gate__card--bottom');
85 }
86
87 if (design.backgroundImage) {
88 const bg = document.createElement('div');
89 bg.className = 'king-addons-age-gate__background';
90 bg.style.backgroundImage = 'url(' + design.backgroundImage + ')';
91 cardEl.prepend(bg);
92 }
93
94 if (design.animation && design.animation !== 'none') {
95 rootEl.classList.add('king-addons-age-gate--animate-' + design.animation);
96 }
97 }
98
99 /**
100 * Shows the overlay.
101 */
102 function showOverlay(rootEl, data) {
103 rootEl.classList.add('king-addons-age-gate--visible');
104 rootEl.setAttribute('aria-hidden', 'false');
105 const overlay = rootEl.querySelector('.king-addons-age-gate__overlay');
106 if (overlay) {
107 overlay.setAttribute('aria-hidden', 'true');
108 }
109 }
110
111 /**
112 * Renders simple Yes/No mode.
113 */
114 function renderYesNo(wrapper, data, localState) {
115 wrapper.innerHTML = '';
116 const title = document.createElement('h2');
117 title.className = 'king-addons-age-gate__title';
118 title.textContent = data.texts.title;
119
120 const subtitle = document.createElement('p');
121 subtitle.className = 'king-addons-age-gate__subtitle';
122 subtitle.textContent = data.mode === 'minimum'
123 ? data.texts.subtitle + ' (' + data.minAge + '+)'
124 : data.texts.subtitle;
125
126 const buttons = document.createElement('div');
127 buttons.className = 'king-addons-age-gate__buttons';
128
129 const yesBtn = buildButton('king-addons-age-gate__button king-addons-age-gate__button--allow', data.texts.yes);
130 const noBtn = buildButton('king-addons-age-gate__button king-addons-age-gate__button--deny', data.texts.no);
131
132 const consent = buildConsent(data);
133
134 yesBtn.addEventListener('click', () => {
135 if (consent && !consent.checkbox.checked) {
136 showMessage(wrapper, data.behaviour.blockMessage || 'Please confirm consent.');
137 return;
138 }
139 setStatus('allowed', localState.cookieDays);
140 closeOverlay();
141 });
142
143 noBtn.addEventListener('click', () => {
144 setStatus('denied', localState.cookieDays);
145 if (data.behaviour.denyAction === 'redirect' && data.behaviour.denyRedirectUrl) {
146 window.location.href = data.behaviour.denyRedirectUrl;
147 } else {
148 renderBlocked(wrapper, data);
149 }
150 });
151
152 buttons.appendChild(yesBtn);
153 buttons.appendChild(noBtn);
154
155 appendLogo(wrapper, data.design);
156 wrapper.appendChild(title);
157 wrapper.appendChild(subtitle);
158 if (consent) {
159 wrapper.appendChild(consent.container);
160 }
161 wrapper.appendChild(buttons);
162 }
163
164 /**
165 * Renders DOB form.
166 */
167 function renderDob(wrapper, data, localState) {
168 wrapper.innerHTML = '';
169 const dobConfig = data.dob || { format: 'dmy', errors: { invalid: 'Invalid date.', denied: 'Access denied.' } };
170
171 const title = document.createElement('h2');
172 title.className = 'king-addons-age-gate__title';
173 title.textContent = data.texts.title;
174
175 const subtitle = document.createElement('p');
176 subtitle.className = 'king-addons-age-gate__subtitle';
177 subtitle.textContent = data.texts.subtitle + ' (' + data.minAge + '+)';
178
179 const grid = document.createElement('div');
180 grid.className = 'king-addons-age-gate__field-grid';
181
182 const inputs = buildDobInputs(dobConfig.format || 'dmy');
183 inputs.forEach((input) => grid.appendChild(input));
184
185 const consent = buildConsent(data);
186
187 const buttons = document.createElement('div');
188 buttons.className = 'king-addons-age-gate__buttons';
189 const submitBtn = buildButton('king-addons-age-gate__button king-addons-age-gate__button--allow', data.texts.yes);
190 const declineBtn = buildButton('king-addons-age-gate__button king-addons-age-gate__button--deny', data.texts.no);
191
192 const message = document.createElement('div');
193 message.className = 'king-addons-age-gate__message';
194 message.style.display = 'none';
195
196 submitBtn.addEventListener('click', () => {
197 if (consent && !consent.checkbox.checked) {
198 showMessage(wrapper, data.behaviour.blockMessage || dobConfig.errors.invalid);
199 return;
200 }
201 message.style.display = 'none';
202 const params = new URLSearchParams();
203 params.append('action', data.ajax.action);
204 params.append('nonce', data.ajax.nonce);
205 params.append('day', inputs.day.value || '');
206 params.append('month', inputs.month.value || '');
207 params.append('year', inputs.year.value || '');
208
209 submitBtn.disabled = true;
210 submitBtn.textContent = data.texts.yes + '...';
211
212 fetch(data.ajax.url, {
213 method: 'POST',
214 headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
215 body: params.toString(),
216 }).then((response) => response.json())
217 .then((resp) => {
218 if (resp && resp.success) {
219 setStatus('allowed', localState.cookieDays);
220 closeOverlay();
221 } else {
222 const msg = resp && resp.data && resp.data.message ? resp.data.message : dobConfig.errors.denied;
223 showInlineMessage(msg);
224 setStatus('denied', localState.cookieDays);
225 }
226 })
227 .catch(() => {
228 showInlineMessage(dobConfig.errors.invalid);
229 })
230 .finally(() => {
231 submitBtn.disabled = false;
232 submitBtn.textContent = data.texts.yes;
233 });
234 });
235
236 declineBtn.addEventListener('click', () => {
237 setStatus('denied', localState.cookieDays);
238 if (data.behaviour.denyAction === 'redirect' && data.behaviour.denyRedirectUrl) {
239 window.location.href = data.behaviour.denyRedirectUrl;
240 } else {
241 renderBlocked(wrapper, data);
242 }
243 });
244
245 buttons.appendChild(submitBtn);
246 buttons.appendChild(declineBtn);
247
248 appendLogo(wrapper, data.design);
249 wrapper.appendChild(title);
250 wrapper.appendChild(subtitle);
251 wrapper.appendChild(grid);
252 if (consent) {
253 wrapper.appendChild(consent.container);
254 }
255 wrapper.appendChild(buttons);
256 wrapper.appendChild(message);
257
258 function showInlineMessage(text) {
259 message.textContent = text;
260 message.style.display = 'block';
261 }
262 }
263
264 /**
265 * Builds DOB inputs based on format.
266 */
267 function buildDobInputs(format) {
268 const day = document.createElement('input');
269 day.type = 'number';
270 day.min = '1';
271 day.max = '31';
272 day.placeholder = 'DD';
273 day.className = 'king-addons-age-gate__input';
274
275 const month = document.createElement('input');
276 month.type = 'number';
277 month.min = '1';
278 month.max = '12';
279 month.placeholder = 'MM';
280 month.className = 'king-addons-age-gate__input';
281
282 const year = document.createElement('input');
283 year.type = 'number';
284 year.min = '1900';
285 year.placeholder = 'YYYY';
286 year.className = 'king-addons-age-gate__input';
287
288 const parts = [];
289 if (format === 'mdy') {
290 parts.push(month, day, year);
291 } else if (format === 'ymd') {
292 parts.push(year, month, day);
293 } else {
294 parts.push(day, month, year);
295 }
296
297 parts.day = day;
298 parts.month = month;
299 parts.year = year;
300 return parts;
301 }
302
303 /**
304 * Renders blocked message.
305 */
306 function renderBlocked(wrapper, data) {
307 wrapper.innerHTML = '';
308 const title = document.createElement('h2');
309 title.className = 'king-addons-age-gate__title';
310 title.textContent = data.texts.title;
311
312 const message = document.createElement('p');
313 message.className = 'king-addons-age-gate__message';
314 message.style.display = 'block';
315 message.textContent = data.behaviour.blockMessage || data.texts.block;
316
317 appendLogo(wrapper, data.design);
318 wrapper.appendChild(title);
319 wrapper.appendChild(message);
320
321 if (data.behaviour.denyRedirectUrl) {
322 const buttons = document.createElement('div');
323 buttons.className = 'king-addons-age-gate__buttons';
324 const goBtn = buildButton('king-addons-age-gate__button king-addons-age-gate__button--allow', data.texts.no);
325 goBtn.addEventListener('click', () => {
326 window.location.href = data.behaviour.denyRedirectUrl;
327 });
328 buttons.appendChild(goBtn);
329 wrapper.appendChild(buttons);
330 }
331 }
332
333 /**
334 * Builds consent checkbox if required.
335 */
336 function buildConsent(data) {
337 if (!data.behaviour || !data.behaviour.consentCheckbox) {
338 return null;
339 }
340 const container = document.createElement('label');
341 container.className = 'king-addons-age-gate__subtitle';
342 const checkbox = document.createElement('input');
343 checkbox.type = 'checkbox';
344 checkbox.style.marginRight = '8px';
345 container.appendChild(checkbox);
346 const labelText = data.behaviour.consentLabel || 'I agree to the policy.';
347 container.appendChild(document.createTextNode(labelText));
348 return {container, checkbox};
349 }
350
351 /**
352 * Utility to create button.
353 */
354 function buildButton(classes, text) {
355 const button = document.createElement('button');
356 button.type = 'button';
357 button.className = classes;
358 button.textContent = text;
359 return button;
360 }
361
362 /**
363 * Appends logo if provided.
364 */
365 function appendLogo(wrapper, design) {
366 if (!design || !design.logo) {
367 return;
368 }
369 const logo = document.createElement('img');
370 logo.src = design.logo;
371 logo.alt = '';
372 logo.className = 'king-addons-age-gate__logo';
373 wrapper.appendChild(logo);
374 }
375
376 /**
377 * Shows a toast-like message within wrapper.
378 */
379 function showMessage(wrapper, text) {
380 let message = wrapper.querySelector('.king-addons-age-gate__message');
381 if (!message) {
382 message = document.createElement('div');
383 message.className = 'king-addons-age-gate__message';
384 wrapper.appendChild(message);
385 }
386 message.textContent = text;
387 message.style.display = 'block';
388 }
389
390 /**
391 * Sets cookie and updates state.
392 */
393 function setStatus(status, days) {
394 const revision = payload.cookie && payload.cookie.revision ? payload.cookie.revision : '';
395 const value = encodeURIComponent(status + '|' + revision);
396 let cookie = payload.cookie.name + '=' + value + '; path=/; SameSite=Lax';
397 if (payload.cookie.domain) {
398 cookie += '; domain=' + payload.cookie.domain;
399 }
400 if (days > 0) {
401 const date = new Date();
402 date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
403 cookie += '; expires=' + date.toUTCString();
404 }
405 document.cookie = cookie;
406 state.status = status;
407 }
408
409 /**
410 * Locks document scroll.
411 */
412 function lockScroll() {
413 document.documentElement.dataset.kaAgeGateScroll = document.documentElement.style.overflow || '';
414 document.documentElement.style.overflow = 'hidden';
415 }
416
417 /**
418 * Restores scroll and hides overlay.
419 */
420 function closeOverlay() {
421 const previous = document.documentElement.dataset.kaAgeGateScroll || '';
422 document.documentElement.style.overflow = previous;
423 root.classList.remove('king-addons-age-gate--visible');
424 }
425
426 /**
427 * Cookie days resolver based on behaviour.
428 */
429 function resolveCookieDays(data) {
430 if (data.behaviour && data.behaviour.repeatMode) {
431 if (data.behaviour.repeatMode === 'session') {
432 return 0;
433 }
434 if (data.behaviour.repeatMode === 'once') {
435 return 3650;
436 }
437 if (data.behaviour.repeatMode === 'days') {
438 return data.behaviour.repeatDays || data.cookie.days || 30;
439 }
440 }
441 return data.cookie && data.cookie.days ? data.cookie.days : 30;
442 }
443 })();
444
445
446
447