Skip to content

Commit 5e88b1b

Browse files
committed
Merge branch 'all-in-one-chat-as-iframe.ag' into release_6.57
2 parents f511537 + 07bd4f8 commit 5e88b1b

13 files changed

Lines changed: 803 additions & 503 deletions

js/apbct-public-bundle_ext-protection.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/apbct-public-bundle_ext-protection.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/apbct-public-bundle_ext-protection_comm-func.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/apbct-public-bundle_ext-protection_comm-func.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/apbct-public-bundle_full-protection.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/apbct-public-bundle_full-protection.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/apbct-public-bundle_full-protection_comm-func.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/apbct-public-bundle_full-protection_comm-func.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/src/apbct-public--5--external-forms.js

Lines changed: 159 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,10 @@ function apbctReplaceInputsValuesFromOtherForm(formSource, formTarget) {
375375
});
376376
});
377377
}
378+
378379
// clear protected iframes list
379-
apbctLocalStorage.set('apbct_iframes_protected', []);
380+
ctProtectOutsideFunctionalClearLocalStorage();
381+
380382
window.addEventListener('load', function() {
381383
if ( ! +ctPublic.settings__forms__check_external ) {
382384
return;
@@ -386,120 +388,141 @@ window.addEventListener('load', function() {
386388
ctProtectExternal();
387389
catchDynamicRenderedForm();
388390
catchNextendSocialLoginForm();
389-
ctProtectOutsideIframe();
391+
ctProtectOutsideFunctionalOnTagsType('div');
392+
ctProtectOutsideFunctionalOnTagsType('iframe');
390393
}, 2000);
391394

392395
ctProtectKlaviyoForm();
393396
});
394397

395-
/**
396-
* Protect klaviyo forms
397-
*/
398-
function ctProtectKlaviyoForm() {
399-
if (!document.querySelector('link[rel="dns-prefetch"][href="//static.klaviyo.com"]')) {
400-
return;
401-
}
402-
403-
let i = setInterval(() => {
404-
const klaviyoForms = document.querySelectorAll('form.klaviyo-form');
405-
if (klaviyoForms.length) {
406-
clearInterval(i);
407-
klaviyoForms.forEach((form, index) => {
408-
apbctProcessExternalFormKlaviyo(form, index, document);
409-
});
410-
}
411-
}, 500);
412-
}
398+
let ctProtectOutsideFunctionalCheckPerformed;
413399

414400
/**
415-
* Protect klaviyo forms
416-
* @param {HTMLElement} form
417-
* @param {int} iterator
418-
* @param {HTMLElement} documentObject
401+
* Protect outside functional. Tags div and iframe supported.
402+
* @param {string} tagType
419403
*/
420-
function apbctProcessExternalFormKlaviyo(form, iterator, documentObject) {
421-
const btn = form.querySelector('button[type="button"].needsclick');
422-
if (!btn) {
423-
return;
404+
function ctProtectOutsideFunctionalOnTagsType(tagType) {
405+
let entityTagsAny = document.querySelectorAll(tagType);
406+
if (entityTagsAny.length > 0) {
407+
entityTagsAny.forEach(function(entity) {
408+
let protectedType = ctProtectOutsideFunctionalIsTagIntegrated(entity);
409+
if (false !== protectedType) {
410+
let lsStorageName = 'apbct_outside_functional_protected_tags__' + protectedType;
411+
let lsUniqueName = entity.id !== '' ? entity.id : false;
412+
lsUniqueName = false === lsUniqueName && entity.className !== '' ? entity.className : lsUniqueName;
413+
// todo we can not protect any entity that has no id and class :(
414+
// pass if is already protected
415+
if (
416+
false === lsUniqueName ||
417+
(
418+
false !== apbctLocalStorage.get(lsStorageName) &&
419+
apbctLocalStorage.get(lsStorageName).length > 0 &&
420+
apbctLocalStorage.get(lsStorageName)[0].indexOf(lsUniqueName) !== -1
421+
)
422+
) {
423+
return;
424+
}
425+
ctProtectOutsideFunctionalHandler(entity, lsStorageName, lsUniqueName);
426+
}
427+
});
424428
}
425-
btn.disabled = true;
426-
427-
const forceAction = document.createElement('input');
428-
forceAction.name = 'action';
429-
forceAction.value = 'cleantalk_force_ajax_check';
430-
forceAction.type = 'hidden';
431-
form.appendChild(forceAction);
432-
433-
let cover = document.createElement('div');
434-
cover.id = 'apbct-klaviyo-cover';
435-
cover.style.width = '100%';
436-
cover.style.height = '100%';
437-
cover.style.background = 'black';
438-
cover.style.opacity = 0;
439-
cover.style.position = 'absolute';
440-
cover.style.top = 0;
441-
cover.style.cursor = 'pointer';
442-
cover.onclick = function(e) {
443-
sendAjaxCheckingFormData(form);
444-
};
445-
btn.parentNode.style.position = 'relative';
446-
btn.parentNode.appendChild(cover);
447429
}
448430

449431
/**
450-
* Protect forms placed in iframe with outside src
432+
* Check if the entity must be protected
433+
*
434+
* @param {HTMLElement} entity
435+
* @return {string|false}
451436
*/
452-
function ctProtectOutsideIframe() {
453-
let iframes = document.querySelectorAll('iframe');
454-
if (iframes.length > 0) {
455-
iframes.forEach(function(iframe) {
456-
if (iframe.src.indexOf('form.typeform.com') !== -1 ||
457-
iframe.src.indexOf('forms.zohopublic.com') !== -1 ||
458-
iframe.src.indexOf('link.surepathconnect.com') !== -1 ||
459-
iframe.src.indexOf('hello.dubsado.com') !== -1 ||
460-
iframe.classList.contains('hs-form-iframe') ||
461-
( iframe.src.indexOf('facebook.com') !== -1 && iframe.src.indexOf('plugins/comments.php') !== -1) ||
462-
iframe.id.indexOf('chatway_widget_app') !== -1
437+
function ctProtectOutsideFunctionalIsTagIntegrated(entity) {
438+
if (entity.tagName !== undefined) {
439+
if (entity.tagName === 'IFRAME') {
440+
if (entity.src.indexOf('form.typeform.com') !== -1 ||
441+
entity.src.indexOf('forms.zohopublic.com') !== -1 ||
442+
entity.src.indexOf('link.surepathconnect.com') !== -1 ||
443+
entity.src.indexOf('hello.dubsado.com') !== -1 ||
444+
entity.classList.contains('hs-form-iframe') ||
445+
( entity.src.indexOf('facebook.com') !== -1 && entity.src.indexOf('plugins/comments.php') !== -1) ||
446+
entity.id.indexOf('chatway_widget_app') !== -1
463447
) {
464-
// pass if is already protected
465-
if (false !== apbctLocalStorage.get('apbct_iframes_protected') &&
466-
apbctLocalStorage.get('apbct_iframes_protected').length > 0 &&
467-
typeof iframe.id !== 'undefined' &&
468-
apbctLocalStorage.get('apbct_iframes_protected').indexOf[iframe.id] !== -1
469-
) {
470-
return;
471-
}
472-
ctProtectOutsideIframeHandler(iframe);
448+
return entity.tagName;
473449
}
474-
});
450+
}
451+
if (entity.tagName === 'DIV') {
452+
if (
453+
entity.className.indexOf('Window__Content-sc') !== -1 || // all in one chat widget
454+
entity.className.indexOf('WidgetBackground__Content-sc') !== -1 // all in one contact form widget
455+
) {
456+
return entity.tagName;
457+
}
458+
}
475459
}
460+
return false;
476461
}
477462

478-
let ctProtectOutsideIframeCheck;
479463
/**
480464
* Protect forms placed in iframe with outside src handler
481-
* @param {HTMLElement} iframe
465+
*
466+
* @param {HTMLElement} entity
467+
* @param {string} lsStorageName
468+
* @param {string|false} lsUniqueName
482469
*/
483-
function ctProtectOutsideIframeHandler(iframe) {
470+
function ctProtectOutsideFunctionalHandler(entity, lsStorageName, lsUniqueName) {
484471
let originParentPosition = null;
485-
let iframeParent = null;
472+
let entityParent = null;
486473

487-
if (iframe.parentNode !== undefined) {
488-
iframeParent = iframe.parentNode;
474+
if (entity.parentNode !== undefined) {
475+
entityParent = entity.parentNode;
489476
} else {
490477
return;
491478
}
492479

480+
if (
481+
entityParent.style !== undefined &&
482+
entityParent.style !== null &&
483+
entityParent.style.position !== undefined
484+
) {
485+
entityParent.style.position = originParentPosition;
486+
} else {
487+
entityParent.style.position = 'relative';
488+
}
489+
entityParent.appendChild(ctProtectOutsideFunctionalGenerateCover());
490+
let entitiesProtected = apbctLocalStorage.get(lsStorageName);
491+
if (false === entitiesProtected) {
492+
entitiesProtected = [];
493+
}
494+
if (lsUniqueName) {
495+
entitiesProtected.push(lsUniqueName);
496+
apbctLocalStorage.set(lsStorageName, entitiesProtected);
497+
}
498+
}
499+
500+
/**
501+
* Clear local storage for OutsideFunctional protection
502+
*
503+
*/
504+
function ctProtectOutsideFunctionalClearLocalStorage() {
505+
apbctLocalStorage.set('apbct_outside_functional_protected_tags__DIV', []);
506+
apbctLocalStorage.set('apbct_outside_functional_protected_tags__IFRAME', []);
507+
}
508+
509+
/**
510+
* Generate cover for outside functional protection
511+
*
512+
* @return {HTMLElement} cover
513+
*/
514+
function ctProtectOutsideFunctionalGenerateCover() {
493515
let cover = document.createElement('div');
494516
cover.style.width = '100%';
495517
cover.style.height = '100%';
496518
cover.style.background = 'black';
497519
cover.style.opacity = 0;
498520
cover.style.position = 'absolute';
499521
cover.style.top = 0;
522+
cover.style.zIndex = 9999;
500523
cover.setAttribute('name', 'apbct_cover');
501524
cover.onclick = function(e) {
502-
if (ctProtectOutsideIframeCheck === undefined) {
525+
if (ctProtectOutsideFunctionalCheckPerformed === undefined) {
503526
let currentDiv = e.currentTarget;
504527
currentDiv.style.opacity = 0.5;
505528
let preloader = document.createElement('div');
@@ -529,22 +552,22 @@ function ctProtectOutsideIframeHandler(iframe) {
529552
{
530553
async: false,
531554
callback: function(result) {
532-
ctProtectOutsideIframeCheck = true;
555+
ctProtectOutsideFunctionalCheckPerformed = true;
533556
let callbackError = false;
534557
if (
535558
typeof result !== 'object' ||
536559
!result.hasOwnProperty('apbct') ||
537560
!result.apbct.hasOwnProperty('blocked')
538561
) {
539-
console.warn('APBCT outside iframe check error, skip check.');
562+
console.warn('APBCT outside functional check error, skip check.');
540563
callbackError = true;
541564
}
542565
const comment = result.apbct.comment !== undefined ?
543566
result.apbct.comment :
544567
'Blocked by CleanTalk Anti-Spam';
545568
if (result.apbct.blocked === false || callbackError) {
546-
document.querySelectorAll('div.apbct-iframe-preloader').forEach(function(el) {
547-
el.parentNode.remove();
569+
document.querySelectorAll('div[name="apbct_cover"]').forEach(function(el) {
570+
el.remove();
548571
});
549572
} else {
550573
document.querySelectorAll('.apbct-iframe-preloader-text').forEach((el) => {
@@ -559,24 +582,61 @@ function ctProtectOutsideIframeHandler(iframe) {
559582
);
560583
}
561584
};
562-
if (
563-
iframeParent.style !== undefined &&
564-
iframeParent.style !== null &&
565-
iframeParent.style.position !== undefined
566-
) {
567-
iframeParent.style.position = originParentPosition;
568-
} else {
569-
iframeParent.style.position = 'relative';
570-
}
571-
iframeParent.appendChild(cover);
572-
let iframes = apbctLocalStorage.get('apbct_iframes_protected');
573-
if (false === iframes) {
574-
iframes = [];
585+
return cover;
586+
}
587+
588+
/**
589+
* Protect klaviyo forms
590+
*/
591+
function ctProtectKlaviyoForm() {
592+
if (!document.querySelector('link[rel="dns-prefetch"][href="//static.klaviyo.com"]')) {
593+
return;
575594
}
576-
if (typeof iframe.id !== 'undefined') {
577-
iframes.push(iframe.id);
578-
apbctLocalStorage.set('apbct_iframes_protected', iframes);
595+
596+
let i = setInterval(() => {
597+
const klaviyoForms = document.querySelectorAll('form.klaviyo-form');
598+
if (klaviyoForms.length) {
599+
clearInterval(i);
600+
klaviyoForms.forEach((form, index) => {
601+
apbctProcessExternalFormKlaviyo(form, index, document);
602+
});
603+
}
604+
}, 500);
605+
}
606+
607+
/**
608+
* Protect klaviyo forms
609+
* @param {HTMLElement} form
610+
* @param {int} iterator
611+
* @param {HTMLElement} documentObject
612+
*/
613+
function apbctProcessExternalFormKlaviyo(form, iterator, documentObject) {
614+
const btn = form.querySelector('button[type="button"].needsclick');
615+
if (!btn) {
616+
return;
579617
}
618+
btn.disabled = true;
619+
620+
const forceAction = document.createElement('input');
621+
forceAction.name = 'action';
622+
forceAction.value = 'cleantalk_force_ajax_check';
623+
forceAction.type = 'hidden';
624+
form.appendChild(forceAction);
625+
626+
let cover = document.createElement('div');
627+
cover.id = 'apbct-klaviyo-cover';
628+
cover.style.width = '100%';
629+
cover.style.height = '100%';
630+
cover.style.background = 'black';
631+
cover.style.opacity = 0;
632+
cover.style.position = 'absolute';
633+
cover.style.top = 0;
634+
cover.style.cursor = 'pointer';
635+
cover.onclick = function(e) {
636+
sendAjaxCheckingFormData(form);
637+
};
638+
btn.parentNode.style.position = 'relative';
639+
btn.parentNode.appendChild(cover);
580640
}
581641

582642
/**

0 commit comments

Comments
 (0)