Fix widget reset code

This commit is contained in:
Taras Kushnir
2026-01-20 11:13:03 +02:00
parent 9f101a13ff
commit cab8ae71e2
3 changed files with 63 additions and 12 deletions
+16
View File
@@ -19,6 +19,17 @@
function onCaptchaErrored() {
console.log("Errored callback called!");
}
function changeWidget() {
let autoWidget = window.privateCaptcha.autoWidget;
if (autoWidget) {
const options = {
theme: 'dark',
lang: 'fr',
debug: true,
};
autoWidget.reset(options);
}
}
</script>
</head>
<body class='h-full pc-vertical-stretch'>
@@ -57,6 +68,11 @@
</form>
</div>
</div>
<div class="mt-8">
<button type="button" class="pc-internal-form-button pc-internal-form-button-secondary pc-internal-button-smaller" onclick="changeWidget()">
Change
</button>
</div>
</div>
</div>
</section>
+25 -4
View File
@@ -140,7 +140,7 @@ export class CaptchaElement extends SafeHTMLElement {
this._overridesSheet = null;
}
connectedCallback() {
update() {
this._debug = this.getAttribute('debug');
this._error = null;
this._displayMode = this.getAttribute('display-mode');
@@ -154,6 +154,11 @@ export class CaptchaElement extends SafeHTMLElement {
const extraStyles = this.getAttribute('extra-styles');
this.updateStyles(extraStyles);
}
connectedCallback() {
this.update();
// init
const canShow = (this._displayMode == DISPLAY_WIDGET);
this.setState(STATE_EMPTY, canShow);
@@ -162,6 +167,7 @@ export class CaptchaElement extends SafeHTMLElement {
/**
* @param {string} state
* @param {boolean} canShow
* @returns {boolean} if changed
*/
setState(state, canShow) {
if (state == this._state) {
@@ -169,11 +175,28 @@ export class CaptchaElement extends SafeHTMLElement {
if (DISPLAY_POPUP === this._displayMode) {
this._syncHostClass(canShow);
}
return;
return false;
}
if (this._debug) { console.debug(`[privatecaptcha][progress] change state. old=${this._state} new=${state}`); }
this.render(state, canShow);
this._state = state;
return true;
}
/**
* Rebuilds the widget UI inside the shadow DOM based on the given state and
* visibility settings. This updates the interactive area contents, applies
* host element CSS classes (including popup-related behavior), and binds
* the checkbox event handler when needed.
*
* @param {string} state - The new widget state (for example, empty, loading, or error).
* @param {boolean} canShow - Whether the widget is allowed to be shown / expanded to the user.
* @returns {void}
*/
render(state, canShow) {
const activeArea = document.createElement('div');
activeArea.className = 'pc-interactive-area';
let bindCheckEvent = false;
@@ -223,8 +246,6 @@ export class CaptchaElement extends SafeHTMLElement {
this._syncHostClass(showPopupIfNeeded);
this._state = state;
const widget = document.createElement('div');
widget.className = 'pc-captcha-widget';
widget.appendChild(activeArea);
+22 -8
View File
@@ -81,7 +81,11 @@ export class CaptchaWidget {
_createCaptchaElement() {
const captchaEl = document.createElement('private-captcha');
this._updateCaptchaElement(captchaEl);
return captchaEl;
}
_updateCaptchaElement(captchaEl) {
captchaEl.setAttribute('lang', this._options.lang);
captchaEl.setAttribute('theme', this._options.theme);
captchaEl.setAttribute('extra-styles', this._options.styles);
@@ -91,8 +95,6 @@ export class CaptchaWidget {
}
captchaEl.setAttribute('display-mode', this._options.displayMode);
return captchaEl;
}
/**
@@ -311,12 +313,18 @@ export class CaptchaWidget {
this._puzzle = null;
this._solution = null;
this._errorCode = errors.ERROR_NO_ERROR;
this.setOptions(options);
this.setState(STATE_EMPTY);
this.setProgressState(STATE_EMPTY);
const pcElement = this._element.querySelector('private-captcha');
if (pcElement) {
this._updateCaptchaElement(pcElement);
// propagate the styles
pcElement.update();
}
this.setProgressState(STATE_EMPTY, true /*force refresh*/);
this.ensureNoSolutionField();
this._userStarted = false;
this._apiTriggered = false;
this.setOptions(options);
}
updateStyles() {
@@ -520,8 +528,10 @@ export class CaptchaWidget {
/**
* Updates the "UI" state of the widget.
* @param {string} state
* @param {boolean} forceRefresh
* @returns {boolean} if changed
*/
setProgressState(state) {
setProgressState(state, forceRefresh = false) {
// NOTE: hidden display mode is taken care of inside setState() even when (_userStarted == true)
const canShow = this._userStarted ||
(DISPLAY_WIDGET === this._options.displayMode) ||
@@ -529,10 +539,14 @@ export class CaptchaWidget {
const pcElement = this._element.querySelector('private-captcha');
if (pcElement) {
pcElement.setError(this._errorCode);
pcElement.setState(state, canShow);
}
else {
const changed = pcElement.setState(state, canShow);
if (!changed && forceRefresh) {
pcElement.render(state, canShow);
}
return changed;
} else {
console.error('[privatecaptcha] component not found when changing state');
return false;
}
}