From 28ba7ed86028ffada596de1da544866b317e4749 Mon Sep 17 00:00:00 2001 From: Taras Kushnir Date: Wed, 14 Jan 2026 09:54:09 +0200 Subject: [PATCH] Create html element explicitly --- cmd/viewwidget/index.html | 1 - widget/js/html.js | 52 ++++++++++++++++++++++----------------- widget/js/widget.js | 18 +++++++++++++- 3 files changed, 47 insertions(+), 24 deletions(-) diff --git a/cmd/viewwidget/index.html b/cmd/viewwidget/index.html index 7bd91070..8d5fe087 100644 --- a/cmd/viewwidget/index.html +++ b/cmd/viewwidget/index.html @@ -48,7 +48,6 @@ data-errored-callback="onCaptchaErrored" data-styles="--border-radius: .75rem; --border: 1px dashed #f00; font-size: 16px; --extra-spacing: 8px; display: block; height: 100%;" data-display-mode="widget" - data-debug="true" {{ if .Debug }}data-debug="{{.Debug}}"{{end}} {{ if .Mode }}data-start-mode="{{.Mode}}"{{end}}> diff --git a/widget/js/html.js b/widget/js/html.js index 64ebe9df..113dff2d 100644 --- a/widget/js/html.js +++ b/widget/js/html.js @@ -75,9 +75,23 @@ function errorDescription(code, strings) { export class CaptchaElement extends SafeHTMLElement { constructor() { super(); + this._state = ''; - // create shadow dom root this._root = this.attachShadow({ mode: 'open' }); + + this._debug = false; + this._error = null; + this._displayMode = DISPLAY_HIDDEN; + this._lang = 'en'; + + // Add CSS + const sheet = new CSSStyleSheet(); + sheet.replaceSync(styles); + this._root.adoptedStyleSheets = [sheet]; + this._overridesSheet = null; + } + + connectedCallback() { this._debug = this.getAttribute('debug'); this._error = null; this._displayMode = this.getAttribute('display-mode'); @@ -87,19 +101,10 @@ export class CaptchaElement extends SafeHTMLElement { this._lang = 'en'; } - // add CSS - const sheet = new CSSStyleSheet(); - sheet.replaceSync(styles); - this._root.adoptedStyleSheets.push(sheet); - this._overridesSheet = null; // add CSS overrides const extraStyles = this.getAttribute('extra-styles'); - if (extraStyles) { - this._overridesSheet = new CSSStyleSheet(); - const cssText = `@layer custom { :host { ${extraStyles} } }`; - this._overridesSheet.replaceSync(cssText); - this._root.adoptedStyleSheets.push(this._overridesSheet); - } + this.updateStyles(extraStyles); + // init const canShow = (this._displayMode == DISPLAY_WIDGET); this.setState(STATE_EMPTY, canShow); @@ -261,7 +266,7 @@ export class CaptchaElement extends SafeHTMLElement { } else { debugText = `[${text}]`; } - debugElement.innerHTML = debugText; + debugElement.textContent = debugText; if (error || this._error) { debugElement.classList.add(DEBUG_ERROR_CLASS); } else { @@ -298,15 +303,18 @@ export class CaptchaElement extends SafeHTMLElement { * @param {string} newValue */ attributeChangedCallback(name, oldValue, newValue) { - if ('progress' === name) { - const progressValue = newValue !== null ? parseFloat(newValue) : NaN; - if (!Number.isNaN(progressValue)) { - this.setProgress(progressValue); - } - } else if ('extra-styles' === name) { - if (oldValue !== newValue) { + if (oldValue === newValue) return; + + switch (name) { + case 'progress': + const progressValue = newValue !== null ? parseFloat(newValue) : NaN; + if (!Number.isNaN(progressValue)) { + this.setProgress(progressValue); + } + break; + case 'extra-styles': this.updateStyles(newValue); - } - } + break; + }; } } diff --git a/widget/js/widget.js b/widget/js/widget.js index b444045c..c4cbca46 100644 --- a/widget/js/widget.js +++ b/widget/js/widget.js @@ -57,7 +57,7 @@ export class CaptchaWidget { // NOTE: this does not work on Safari by (Apple) design if we click a button // "passive" - cannot use preventDefault() form.addEventListener('focusin', this.onFocusIn.bind(this), { passive: true }); - this._element.innerHTML = ``; + this._element.replaceChildren(this._createCaptchaElement()); this._element.addEventListener('privatecaptcha:checked', this.onChecked.bind(this)); if (this._options.storeVariable) { @@ -79,6 +79,22 @@ export class CaptchaWidget { } } + _createCaptchaElement() { + const captchaEl = document.createElement('private-captcha'); + + captchaEl.setAttribute('lang', this._options.lang); + captchaEl.setAttribute('theme', this._options.theme); + captchaEl.setAttribute('extra-styles', this._options.styles); + + if (this._options.debug) { + captchaEl.setAttribute('debug', 'true'); + } + + captchaEl.setAttribute('display-mode', this._options.displayMode); + + return captchaEl; + } + /** * @param {Object} options */