Я пытаюсь исправить проблемы с отзывчивым дизайном Recaptcha, и я думаю, что лучшим решением было бы включить вызов Recaptcha в то же самое всплывающее окно (контейнер), где отображается Checkaptcha Checkbox , но я не знаю, как. Он всегда присоединяется как последний тег div к телу.
Страница (.CS HTML):
<div class="vote-email__field">
<div class="vote-email__captcha" data-dc-component="recaptcha" data-dc-recaptcha-options='{"sitekey" : "@Model.RecaptchaSiteKey", "id" : "vote-modal-id"}'>
</div>
<div class="vote-email__error isDisabled" data-dc-vote-email-ref="errors[]">Error: Please check recaptcha</div>
</div>
компонент recaptcha (. JS):
import BaseComponent from '../../../general/js/base-component';
import eventBus from '../../../general/js/event-bus';
import onReady from './loadRecaptcha';
import { RECAPCHA_RESET, UPDATE_RECAPCHA_GUID } from './events';
export default class RecaptchaComponent extends BaseComponent {
constructor(...args) {
super(...args);
this.voteButton = document.getElementById("js-vote-button");
this.recaptchaChallenge = null;
this.captchaId = null;
onReady(this.init);
if (this.voteButton) {
this.addListener(this.voteButton, "click", () => this.changeChallengeStyleWhenDisplayed(1000));
}
}
changeChallengeStyleWhenDisplayed(timeout) {
window.setTimeout(() => {
try {
if (document.querySelector("body").lastElementChild.lastElementChild.style.zIndex === "2000000000") {
//console.log(true)
//TODO: if recaptcha challenge container is not last element, it will break
document.querySelector("body").lastElementChild.lastElementChild.setAttribute("id", "js-recaptcha-challenge")
this.recaptchaChallenge = document.getElementById("js-recaptcha-challenge");
this.recaptchaChallenge.classList.add("recaptcha__viewport--center");
return;
}
else {
//console.log(false)
this.changeChallengeStyleWhenDisplayed(500);
}
}
catch (error) {
console.error(error);
this.changeChallengeStyleWhenDisplayed(500);
}
}, timeout);
}
init = (grecaptcha) => {
this.grecaptcha = grecaptcha;
this.captchaId = grecaptcha.render(this.element, {
sitekey: this.options.sitekey,
callback: this.successCallback,
'expired-callback': this.reset
});
eventBus.addListener(RECAPCHA_RESET, id => this.onError(id));
};
successCallback = (response) => {
console.log(successCallback);
eventBus.emit(UPDATE_RECAPCHA_GUID, this.options.id, response);
};
onError = (id) => {
if (this.options.id === id) {
this.grecaptcha.reset(this.captchaId);
this.reset();
}
};
reset = () => {
eventBus.emit(UPDATE_RECAPCHA_GUID, this.options.id, null);
};
}
Загрузчик рекапчи (. JS):
const callbackName = 'onRecatpchaLoad';
let isLoaded = false;
const onloadQueue = [];
window[callbackName] = () => {
isLoaded = true;
onloadQueue.forEach(callback => callback(window.grecaptcha));
};
export default function onReady(callback) {
if (isLoaded) {
callback(window.grecaptcha);
} else {
onloadQueue.push(callback);
}
}
function insertScript() {
const script = document.createElement('script');
script.async = true;
script.defer = true;
script.src = `https://www.google.com/recaptcha/api.js?onload=${callbackName}&render=explicit`;
const s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(script, s);
}
insertScript();