Ja - schön und gut aber die ID hatte schon ihren Sinn (natürlich kann man dann keine zwei Formulare auf der gleichen Seite haben).
So wie Deine KI es umgeschrieben hat ist es
falsch und wirkt gar nicht, da diese Klassen im JavaScript umgesetzt werden.
Unten nochmals der nun fertige und korrekte Code. Bitte lasse doch auch die jetzt korrekten Einrückungen vom Style und vom JavaScript so wie sie sind, Du rückst die nie ein und für einen Programmierer ist das sehr unschön und tut schon fast weh
Code: Alles auswählen
<section data-bs-version="5.1" class="vn-mailer" group="Content" id="{{mbr-id}}" data-addcopycheckbox="{{addCopyCheckbox}}" data-copycheckboxlabel="{{copyCheckboxLabel}}" data-addcaptcha="{{addCaptcha}}" data-captchatype="{{captchaType}}" data-hcaptchasitekey="{{hcaptchaSiteKey}}" data-hcaptchatheme="{{hcaptchaTheme}}" data-thankyouurl="{{thankYouUrl}}" data-toastmessage="{{toastMessage}}" data-textcolor="{{textColor}}" data-captchatransparent="{{captchaTransparent}}" data-captchabgcolor="{{captchaBgColor}}" data-captchabordercolor="{{captchaBorderColor}}" data-accentcolor="{{accentColor}}" data-fieldfontsize="{{fieldFontSize}}" data-scrolltoform="{{scrollToForm}}">
<style>
.vn-mailer {
display: none;
}
html.is-builder .vn-mailer {
display: block !important;
padding: 20px;
text-align: center;
border: 2px dashed #e63946;
border-radius: 8px;
background: #fff5f5;
color: #999;
font-size: 13px;
}
.vn-mailer .vnm-editor-only {
display: none;
}
html.is-builder .vn-mailer .vnm-editor-only {
display: block;
}
.vnm-toast {
position: fixed;
bottom: 24px;
left: 50%;
transform: translateX(-50%) translateY(20px);
background: #1d9e75;
color: #fff;
padding: 14px 24px;
border-radius: 8px;
box-shadow: 0 8px 24px rgba(0,0,0,0.2);
font-family: system-ui, sans-serif;
font-size: 14px;
z-index: 999995;
opacity: 0;
transition: opacity 0.3s ease, transform 0.3s ease;
pointer-events: none;
}
.vnm-toast.vnm-toast-show {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
/*
* Von Tommy:
* Beschriftung immer oberhalb des Captchas anzeigen.
*
* WICHTIG:
* Hier darf NICHT ".vn-mailer .vnm-captcha-label" stehen,
* weil das Label per JavaScript in das benachbarte Formular
* eingefügt wird und deshalb nicht innerhalb von .vn-mailer liegt.
*
* Die Klasse darf auf einer Seite mehrfach verwendet werden.
*/
.vnm-captcha-label {
display: block !important;
width: 100% !important;
box-sizing: border-box;
padding-top: 20px !important;
padding-bottom: 10px !important;
margin: 0 !important;
}
/*
* Von Tommy:
* hCaptcha immer unterhalb der Beschriftung anzeigen.
* Gilt für das helle und das dunkle hCaptcha-Design.
*
* Auch dieser Wrapper liegt im benachbarten Formular und
* darf deshalb nicht mit ".vn-mailer" davor angesprochen werden.
*/
.vnm-hcaptcha-wrap {
display: block !important;
width: 100% !important;
max-width: 100%;
clear: both;
box-sizing: border-box;
line-height: 0;
overflow: visible !important;
padding-bottom: 2px;
}
.vnm-hcaptcha-wrap .h-captcha {
display: inline-block !important;
line-height: 0;
overflow: visible !important;
}
.vnm-hcaptcha-wrap iframe {
display: block !important;
overflow: visible !important;
}
</style>
<mbr-parameters>
<header>Formular-Erweiterung</header>
<input type="checkbox" title="'Kopie an mich'-Checkbox einfügen" name="addCopyCheckbox" checked>
<input type="text" title="Checkbox-Text" name="copyCheckboxLabel" value="Kopie an mich senden">
<input type="checkbox" title="Captcha einfügen" name="addCaptcha" checked>
<select title="Captcha-Typ" name="captchaType">
<option value="math">Mathe-Aufgabe (eigenes System)</option>
<option value="hcaptcha" selected>hCaptcha</option>
</select>
<input type="text" title="hCaptcha Site-Key (öffentlich, von hcaptcha.com)" name="hcaptchaSiteKey" value="856eaa44-aec0-4fb6-9034-fd4a2dceacec" placeholder="z.B. 10000000-ffff-ffff-ffff-000000000001">
<select title="hCaptcha-Design" name="hcaptchaTheme" condition="captchaType == 'hcaptcha'">
<option value="light">Hell</option>
<option value="dark" selected>Dunkel</option>
</select>
<header>Optik der eingefügten Felder</header>
<input type="color" title="Textfarbe (Label/Checkbox-Text)" name="textColor" value="#ffffff" selected>
<input type="checkbox" title="Captcha-Box transparent (kein eigener Hintergrund)" name="captchaTransparent" checked>
<input type="color" title="Captcha-Box Hintergrund" name="captchaBgColor" value="#f0f4f8" condition="!captchaTransparent" selected>
<input type="color" title="Captcha-Box Rahmen" name="captchaBorderColor" value="#b8c4d0" selected>
<input type="color" title="Akzentfarbe (Pflichtfeld-Sterne)" name="accentColor" value="#ffffff" selected>
<input type="range" inline title="Schriftgröße Label/Captcha (px)" name="fieldFontSize" min="10" max="24" step="1" value="18">
<header>Nach dem Absenden</header>
<input type="text" title="Danke-Seite (URL, leer = Toast-Meldung statt Weiterleitung)" name="thankYouUrl" value placeholder="/danke.html oder https://...">
<input type="text" title="Toast-Meldung (falls keine Danke-Seite)" name="toastMessage" value="Danke für deine Nachricht!">
<input type="checkbox" title="Zum Formular scrollen statt Seitenanfang (nach Absenden/Fehler)" name="scrollToForm" checked>
</mbr-parameters>
<div class="vnm-editor-only">
🔧 VN Mailer<br>
<small>Unsichtbar auf der Live-Seite. Rüstet das Formular direkt darüber oder darunter mit Kopie-Checkbox/Captcha/Danke-Seite nach.</small>
</div>
<script>
(function() {
if (document.documentElement.classList.contains('is-builder')) return;
var sec = document.currentScript
? document.currentScript.closest('section.vn-mailer')
: document.querySelector('section.vn-mailer');
if (!sec) return;
function attr(name) {
var v = sec.getAttribute(name);
if (!v || v.indexOf('{{') !== -1) {
return '';
}
return v.trim();
}
function truthy(v) {
return v === 'true' || v === 'on' || v === '1';
}
var addCopyCheckbox = truthy(attr('data-addcopycheckbox'));
var copyCheckboxLabel = attr('data-copycheckboxlabel') || 'Kopie an mich senden';
var addCaptcha = truthy(attr('data-addcaptcha'));
var captchaType = attr('data-captchatype') || 'math';
var hcaptchaSiteKey = attr('data-hcaptchasitekey');
var hcaptchaTheme = attr('data-hcaptchatheme') || 'light';
var thankYouUrl = attr('data-thankyouurl');
var toastMessage = attr('data-toastmessage') || 'Danke für deine Nachricht!';
var textColor = attr('data-textcolor') || '#222222';
var captchaTransparent = truthy(attr('data-captchatransparent'));
var captchaBgColor = attr('data-captchabgcolor') || '#f0f4f8';
var captchaBorderColor = attr('data-captchabordercolor') || '#b8c4d0';
var accentColor = attr('data-accentcolor') || '#e63946';
var fieldFontSize = attr('data-fieldfontsize') || '14';
var scrollToForm = truthy(attr('data-scrolltoform'));
/*
* Nur die zwei offiziellen hCaptcha-Designwerte zulassen.
*/
if (
hcaptchaTheme !== 'dark' &&
hcaptchaTheme !== 'light'
) {
hcaptchaTheme = 'light';
}
var labelColorStyle =
'color:' + textColor + ' !important;' +
'font-size:' + fieldFontSize + 'px !important;';
var captchaBgStyle = captchaTransparent
? 'background:transparent;'
: 'background:' + captchaBgColor + ';';
// ── Natives Formular in der Nachbarschaft finden ──────────────
// Sucht bis zu 5 Geschwister-Elemente in jede Richtung ab,
// falls beispielsweise noch ein Trenner-Block dazwischen liegt.
function findNeighborForm() {
var maxSteps = 5;
var prevEl = sec;
for (var i = 0; i < maxSteps; i++) {
prevEl = prevEl.previousElementSibling;
if (!prevEl) break;
var formInPrev = prevEl.tagName === 'FORM'
? prevEl
: prevEl.querySelector('form');
if (formInPrev) {
return formInPrev;
}
}
var nextEl = sec;
for (var j = 0; j < maxSteps; j++) {
nextEl = nextEl.nextElementSibling;
if (!nextEl) break;
var formInNext = nextEl.tagName === 'FORM'
? nextEl
: nextEl.querySelector('form');
if (formInNext) {
return formInNext;
}
}
return null;
}
/*
* Steht der VN-Mailer-Block vor dem Formular, existiert das
* Formular beim Ausführen dieses Script-Tags möglicherweise
* noch nicht im DOM. Deshalb erst nach vollständigem Laden suchen.
*/
function initFormEnhancements() {
var form = findNeighborForm();
if (!form) {
handleRedirectResult(null);
return;
}
runEnhancements(form);
handleRedirectResult(form);
}
if (document.readyState === 'loading') {
document.addEventListener(
'DOMContentLoaded',
initFormEnhancements
);
} else {
initFormEnhancements();
}
function runEnhancements(form) {
function getAssetsBasePath() {
var ref = document.querySelector(
'link[href*="assets/"], script[src*="assets/"]'
);
if (ref) {
var url =
ref.getAttribute('href') ||
ref.getAttribute('src');
var idx = url.indexOf('assets/');
if (idx !== -1) {
return url.substring(
0,
idx + 'assets/'.length
);
}
}
return 'assets/';
}
var base = getAssetsBasePath() + 'vn-mailer/';
// Container, in den neue Felder eingefügt werden.
var dragArea =
form.querySelector('.dragArea') ||
form;
var submitBtnWrap =
dragArea.querySelector('.mbr-section-btn');
function insertField(html) {
var wrap = document.createElement('div');
wrap.className =
'col-lg-12 col-md-12 col-sm-12 form-group mb-3';
wrap.innerHTML = html;
if (submitBtnWrap) {
dragArea.insertBefore(
wrap,
submitBtnWrap
);
} else {
dragArea.appendChild(wrap);
}
return wrap;
}
/*
* Verstecktes Feld mit der Block-ID.
*
* Damit kann bei mehreren VN-Mailer-Instanzen auf einer
* Seite zugeordnet werden, welches Formular abgesendet wurde.
*/
var idField = document.createElement('input');
idField.type = 'hidden';
idField.name = 'vnmailer_id';
idField.value = sec.id || '';
form.appendChild(idField);
// ── „Kopie an mich“-Checkbox einfügen ─────────────────────
if (addCopyCheckbox) {
insertField(
'<label style="' +
'display:flex;' +
'align-items:center;' +
'gap:8px;' +
'font-weight:400;' +
labelColorStyle +
'">' +
'<input type="checkbox" ' +
'name="copy_to_sender" ' +
'style="width:auto;"> ' +
escapeHtmlLocal(copyCheckboxLabel) +
'</label>'
);
}
// ── Captcha einfügen ───────────────────────────────────────
if (
addCaptcha &&
captchaType === 'hcaptcha' &&
hcaptchaSiteKey
) {
var hcaptchaField = insertField(
'<label class="vnm-captcha-label" style="' +
labelColorStyle +
'">' +
'Sicherheitsabfrage ' +
'<span style="color:' +
accentColor +
';">*</span>' +
'</label>' +
'<div class="vnm-hcaptcha-wrap">' +
'<div class="h-captcha" ' +
'data-sitekey="' +
escapeHtmlLocal(hcaptchaSiteKey) +
'" ' +
'data-theme="' +
escapeHtmlLocal(hcaptchaTheme) +
'">' +
'</div>' +
'</div>' +
'<input type="hidden" ' +
'name="vnmailer_hcaptcha_sitekey" ' +
'value="' +
escapeHtmlLocal(hcaptchaSiteKey) +
'">'
);
if (!document.querySelector(
'script[data-vnm-hcaptcha]'
)) {
var hcScript =
document.createElement('script');
hcScript.src =
'https://js.hcaptcha.com/1/api.js';
hcScript.async = true;
hcScript.defer = true;
hcScript.setAttribute(
'data-vnm-hcaptcha',
'1'
);
document.head.appendChild(hcScript);
}
/*
* hCaptcha erzeugt seinen iFrame erst nachträglich.
* Kurz warten und dann etwas mehr Höhe geben, damit
* der untere Rahmen nicht abgeschnitten wird.
*
* Der Inhalt wird dabei nicht skaliert.
*/
(function fixHcaptchaFrame(wrapper, attemptsLeft) {
if (!wrapper || attemptsLeft <= 0) return;
var iframe = wrapper.querySelector('iframe');
if (iframe) {
iframe.style.setProperty(
'display',
'block',
'important'
);
iframe.style.setProperty(
'height',
'80px',
'important'
);
iframe.style.setProperty(
'overflow',
'visible',
'important'
);
wrapper.style.setProperty(
'overflow',
'visible',
'important'
);
return;
}
setTimeout(function() {
fixHcaptchaFrame(
wrapper,
attemptsLeft - 1
);
}, 100);
})(
hcaptchaField.querySelector(
'.vnm-hcaptcha-wrap'
),
100
);
} else if (addCaptcha) {
var captchaWrap = insertField(
'<label class="vnm-captcha-label" style="' +
labelColorStyle +
'">' +
'Sicherheitsabfrage ' +
'<span style="color:' +
accentColor +
';">*</span>' +
'</label>' +
'<div style="' +
'display:flex;' +
'align-items:center;' +
'gap:10px;' +
captchaBgStyle +
'border:1px dashed ' +
captchaBorderColor +
';' +
'border-radius:6px;' +
'padding:10px 12px;' +
'">' +
'<span data-vnm-captcha-q style="' +
labelColorStyle +
'">' +
'Lade…' +
'</span>' +
'<input type="text" ' +
'name="captcha_answer" ' +
'required ' +
'style="' +
'width:70px;' +
'padding:6px;' +
'border:1px solid #ccc;' +
'border-radius:4px;' +
'font-size:' +
fieldFontSize +
'px !important;' +
'">' +
'<input type="hidden" ' +
'name="captcha_token" ' +
'value="">' +
'</div>'
);
fetch(
base + 'captcha.php?t=' + Date.now(),
{
cache: 'no-store'
}
)
.then(function(r) {
return r.json();
})
.then(function(d) {
var qEl = captchaWrap.querySelector(
'[data-vnm-captcha-q]'
);
var tokenEl = captchaWrap.querySelector(
'input[name="captcha_token"]'
);
if (qEl) {
qEl.textContent =
d.question || '?';
}
if (tokenEl) {
tokenEl.value =
d.token || '';
}
})
.catch(function() {});
}
function escapeHtmlLocal(str) {
var div = document.createElement('div');
div.textContent = str || '';
return div.innerHTML;
}
}
// ── Erfolg/Fehler nach echtem Seiten-Reload erkennen ─────────
/*
* native-form-handler.php leitet nach dem Absenden per Redirect
* zurück auf diese Seite und hängt ?vnmailer=success/error an.
*/
function showToast(message) {
var toast = document.createElement('div');
toast.className = 'vnm-toast';
toast.textContent = message;
document.body.appendChild(toast);
requestAnimationFrame(function() {
toast.classList.add('vnm-toast-show');
});
setTimeout(function() {
toast.classList.remove('vnm-toast-show');
setTimeout(function() {
toast.remove();
}, 400);
}, 4000);
}
function onFormSuccess() {
if (thankYouUrl) {
window.location.href = thankYouUrl;
} else {
showToast(toastMessage);
}
}
function handleRedirectResult(form) {
var urlParams =
new URLSearchParams(window.location.search);
var vnmStatus =
urlParams.get('vnmailer');
if (
vnmStatus !== 'success' &&
vnmStatus !== 'error'
) {
return;
}
/*
* Bei mehreren VN-Mailer-Blöcken auf einer Seite nur
* reagieren, wenn diese Instanz tatsächlich gemeint ist.
*/
var targetId =
urlParams.get('vnmailer_id') || '';
if (
targetId &&
sec.id &&
targetId !== sec.id
) {
return;
}
/*
* Zum Formular-Block scrollen statt zum Seitenanfang.
* Nicht bei Erfolg mit einer eigenen Danke-Seite.
*/
if (
scrollToForm &&
form &&
!(
vnmStatus === 'success' &&
thankYouUrl
)
) {
var targetSection =
form.closest('section') ||
form;
targetSection.scrollIntoView({
behavior: 'auto',
block: 'start'
});
}
if (vnmStatus === 'success') {
onFormSuccess();
} else {
var errMsg =
urlParams.get('vnmailer_msg') ||
'Es ist ein Fehler aufgetreten.';
showToast(errMsg);
}
cleanUrlParams();
}
function cleanUrlParams() {
/*
* URL-Parameter entfernen, damit beim Neuladen
* die Meldung nicht erneut erscheint.
*/
var url = new URL(window.location.href);
url.searchParams.delete('vnmailer');
url.searchParams.delete('vnmailer_msg');
url.searchParams.delete('vnmailer_id');
window.history.replaceState(
{},
'',
url.toString()
);
}
})();
</script>
</section>
Die ganzen Kommentare "Von Tommy" kannst du natürlich gerne entfernen lassen - die sind nur für mein Verständnis gedacht.
Weiterhin ist mir aufgefallen das der geheime "Secret Code" vom hCaptcha nach der Neuinstallation bereits im Site-Menü eingetragen war - wie ist das möglich, bzw. das dürfte ja eigentlich nicht sein.