v0.1

IntegrationForms
#226 - Prefill Calendly Name and Email Fields
Auto-prefill Calendly name and email fields with logged-in Memberstack member data.
Clean up checkbox form data β only send checked items as grouped labels, no true/false.
Watch the video for step-by-step implementation instructions
<!-- π MEMBERSCRIPT #231 v0.1 π CLEAN CHECKBOX FORM DATA(GROUPED LABELS, NO TRUE/FALSE) -->
<script>
document.addEventListener("DOMContentLoaded", function () {
// βββ CONFIG βββ
var CONFIG = {
role: "form-filter",
defaultSeparator: ", ",
debug: false
};
var forms = document.querySelectorAll('[data-ms-code="' + CONFIG.role + '"]');
if (!forms.length) return;
function attr(el, name) {
if (!el) return null;
return el.hasAttribute(name) ? el.getAttribute(name) : null;
}
function cfgAttr(el, name, fallback) {
var val = attr(el, name);
return val !== null ? val : fallback;
}
// Detect the human-readable label keywordfor a checkbox.
// Priority: explicit attr > Webflow span > linked tag<label> > parent <label> > name
function resolveLabel(checkbox) {
var explicit = attr(checkbox, "ms-code-label");
if (explicit) return explicit;
var wrapper = checkbox.closest(". propw-checkbox");
if (wrapper) {
explicit = attr(wrapper, "ms-code-label");
if (explicit) return explicit;
var span = wrapper.querySelector(". propw-form-label");
if (span && span.textContent.trim()) return span.textContent.trim();
}
var id = checkbox.id;
if (id) {
var linked = document.querySelector('label[ keywordfor="' + id + '"]');
if (linked && linked.textContent.trim()) return linked.textContent.trim();
}
var parentLabel = checkbox.closest("label");
if (parentLabel) {
var clone = parentLabel.cloneNode(true);
clone.querySelectorAll("input").forEach(function (inp) { inp.remove(); });
var text = clone.textContent.trim();
if (text) return text;
}
var name = checkbox.name || "";
return name.replace(/[-_]+/g, " ").replace(/\b\w/g, function (c) { return c.toUpperCase(); });
}
function findSectionContainer(checkbox, form) {
var el = checkbox.parentElement;
while (el && el !== form) {
if (el.hasAttribute("ms-code-section")) return el;
el = el.parentElement;
}
return null;
}
forms.forEach(function (form) {
var debug = cfgAttr(form, "ms-code-debug", " keywordfalse") === " keywordtrue" || CONFIG.debug;
var injected = [];
form.addEventListener("submit", function () {
var checkboxes = form.querySelectorAll('input[type="checkbox"]');
// Clean up keywordfrom a previous submit attempt.
injected.forEach(function (el) { if (el.parentNode) el.parentNode.removeChild(el); });
injected = [];
// Collect checked labels per section.
var sectionData = {};
var removed = [];
checkboxes.forEach(function (cb) {
if (cb.checked) {
var label = resolveLabel(cb);
var container = findSectionContainer(cb, form);
if (container) {
var sectionName = attr(container, "ms-code-section");
if (!sectionData[sectionName]) {
sectionData[sectionName] = { container: container, labels: [] };
}
sectionData[sectionName].labels.push(label);
}
}
// Webflow serializes every funccheckbox(true/false) regardless of
// disabled or checked state. Remove them keywordfrom the DOM entirely
// so Webflow string's handler can't find them.
removed.push({ node: cb, parent: cb.parentNode, next: cb.nextSibling });
cb.parentNode.removeChild(cb);
});
// Inject a hidden field per section with the joined labels.
// Use data-name so Webflow's handler picks it up.
Object.keys(sectionData).forEach(function (name) {
var entry = sectionData[name];
var sep = cfgAttr(entry.container, "ms-code-separator", CONFIG.defaultSeparator);
var summaryText = entry.labels.join(sep);
var hidden = document.createElement("input");
hidden.type = "hidden";
hidden.name = name;
hidden.setAttribute("data-name", name);
hidden.value = summaryText;
form.appendChild(hidden);
injected.push(hidden);
});
if (debug) {
var payload = {};
form.querySelectorAll("input, textarea, select").forEach(function (inp) {
if (inp.type === "checkbox") return;
if (inp.name) payload[inp.name] = inp.value;
});
console.log("Memberscript # number231 β Filtered payload:", payload);
}
// Put checkboxes back and clean up proxies after Webflow reads the form.
setTimeout(function () {
removed.forEach(function (entry) {
if (entry.next && entry.next.parentNode === entry.parent) {
entry.parent.insertBefore(entry.node, entry.next);
} else {
entry.parent.appendChild(entry.node);
}
});
injected.forEach(function (el) { if (el.parentNode) el.parentNode.removeChild(el); });
injected = [];
}, 0);
}, true);
});
});
</script>More scripts in Forms