Scripts des membres
Une solution basée sur les attributs pour ajouter des fonctionnalités à votre site Webflow.
Il suffit de copier un peu de code, d'ajouter quelques attributs et le tour est joué.
Tous les clients de Memberstack peuvent demander de l'aide dans le Slack 2.0. Veuillez noter qu'il ne s'agit pas de fonctionnalités officielles et que le support ne peut être garanti.

#78 - Effacer les entrées sur le clic
Créez un bouton qui peut effacer les valeurs d'une ou plusieurs entrées.
<!-- 💙 MEMBERSCRIPT #78 v0.1 💙 CLEAR INPUT VALUES ONCLICK -->
<script>
document.addEventListener('DOMContentLoaded', () => {
const clearBtns = document.querySelectorAll('[ms-code-clear-value]');
clearBtns.forEach(btn => {
btn.addEventListener('click', () => {
const fieldIds = btn.getAttribute('ms-code-clear-value').split(',');
fieldIds.forEach(fieldId => {
const input = document.querySelector(`[data-ms-member="${fieldId}"]`);
if (input) {
input.value = '';
}
});
});
});
});
</script>
<!-- 💙 MEMBERSCRIPT #78 v0.1 💙 CLEAR INPUT VALUES ONCLICK -->
<script>
document.addEventListener('DOMContentLoaded', () => {
const clearBtns = document.querySelectorAll('[ms-code-clear-value]');
clearBtns.forEach(btn => {
btn.addEventListener('click', () => {
const fieldIds = btn.getAttribute('ms-code-clear-value').split(',');
fieldIds.forEach(fieldId => {
const input = document.querySelector(`[data-ms-member="${fieldId}"]`);
if (input) {
input.value = '';
}
});
});
});
});
</script>

#77 - Emojis universels
Faites en sorte que vos emojis sur site soient les mêmes sur tous les appareils/OS.
<!-- 💙 MEMBERSCRIPT #77 v0.1 💙 UNIVERSAL EMOJIS -->
<script>
document.querySelectorAll('[ms-code-emoji]').forEach(element => {
var imageUrl = element.getAttribute('ms-code-emoji');
var img = document.createElement('img');
img.src = imageUrl;
var textStyle = window.getComputedStyle(element);
var adjustedHeight = parseFloat(textStyle.fontSize) * 1.0;
img.style.height = adjustedHeight + 'px';
img.style.width = 'auto';
img.style.verticalAlign = 'text-top';
element.innerHTML = ''; // Clears the text content inside the span
element.appendChild(img);
});
</script>
<!-- 💙 MEMBERSCRIPT #77 v0.1 💙 UNIVERSAL EMOJIS -->
<script>
document.querySelectorAll('[ms-code-emoji]').forEach(element => {
var imageUrl = element.getAttribute('ms-code-emoji');
var img = document.createElement('img');
img.src = imageUrl;
var textStyle = window.getComputedStyle(element);
var adjustedHeight = parseFloat(textStyle.fontSize) * 1.0;
img.style.height = adjustedHeight + 'px';
img.style.width = 'auto';
img.style.verticalAlign = 'text-top';
element.innerHTML = ''; // Clears the text content inside the span
element.appendChild(img);
});
</script>

#76 - Visibilité dans le temps
Afficher différents éléments en fonction de l'heure de la journée.
<!-- 💙 MEMBERSCRIPT #76 v0.1 💙 TIME-BASED VISIBILITY -->
<script>
function hideElements() {
const elements = document.querySelectorAll('[ms-code-time]');
elements.forEach(element => {
element.style.display = 'none';
});
}
function displayBasedOnTime() {
const elements = document.querySelectorAll('[ms-code-time]');
const currentTime = new Date();
elements.forEach(element => {
const timeRange = element.getAttribute('ms-code-time');
const [start, end] = timeRange.split(' - ');
const [startHour, startMinute] = start.split(':').map(Number);
const [endHour, endMinute] = end.split(':').map(Number);
let startTime = new Date(currentTime);
startTime.setHours(startHour, startMinute, 0, 0);
let endTime = new Date(currentTime);
endTime.setHours(endHour, endMinute, 0, 0);
// If the end time is earlier than the start time, add a day to the end time
if (endTime < startTime) {
endTime.setDate(endTime.getDate() + 1);
}
if (currentTime >= startTime && currentTime <= endTime) {
element.style.display = 'flex';
}
});
}
// Call the functions
hideElements();
displayBasedOnTime();
</script>
<!-- 💙 MEMBERSCRIPT #76 v0.1 💙 TIME-BASED VISIBILITY -->
<script>
function hideElements() {
const elements = document.querySelectorAll('[ms-code-time]');
elements.forEach(element => {
element.style.display = 'none';
});
}
function displayBasedOnTime() {
const elements = document.querySelectorAll('[ms-code-time]');
const currentTime = new Date();
elements.forEach(element => {
const timeRange = element.getAttribute('ms-code-time');
const [start, end] = timeRange.split(' - ');
const [startHour, startMinute] = start.split(':').map(Number);
const [endHour, endMinute] = end.split(':').map(Number);
let startTime = new Date(currentTime);
startTime.setHours(startHour, startMinute, 0, 0);
let endTime = new Date(currentTime);
endTime.setHours(endHour, endMinute, 0, 0);
// If the end time is earlier than the start time, add a day to the end time
if (endTime < startTime) {
endTime.setDate(endTime.getDate() + 1);
}
if (currentTime >= startTime && currentTime <= endTime) {
element.style.display = 'flex';
}
});
}
// Call the functions
hideElements();
displayBasedOnTime();
</script>

#75 - Entrées de caractères non autorisées
Afficher un message d'erreur personnalisé si un utilisateur saisit un élément que vous avez défini dans une entrée.
<!-- 💙 MEMBERSCRIPT #75 v0.1 💙 DISALOWED CHARACTER INPUTS -->
<script>
document.addEventListener('DOMContentLoaded', function() {
const inputFields = document.querySelectorAll('[ms-code-disallow]');
inputFields.forEach(inputField => {
const errorBlock = inputField.nextElementSibling;
errorBlock.innerHTML = ''; // Use innerHTML to interpret <br> tags
inputField.addEventListener('input', function() {
const rules = inputField.getAttribute('ms-code-disallow').split(')');
let errorMessage = '';
rules.forEach(rule => {
const parts = rule.trim().split('=');
const ruleType = parts[0].substring(1); // Remove the opening parenthesis
const disallowedValue = parts[1];
if (ruleType.startsWith('custom')) {
const disallowedChar = ruleType.split('-')[1]; // Extract the character after the '-'
if (inputField.value.includes(disallowedChar)) {
errorMessage += disallowedValue + '<br>'; // Add line break
}
} else if (ruleType === 'space' && inputField.value.includes(' ')) {
errorMessage += disallowedValue + '<br>'; // Add line break
} else if (ruleType === 'number' && /\d/.test(inputField.value)) {
errorMessage += disallowedValue + '<br>'; // Add line break
} else if (ruleType === 'special' && /[^a-zA-Z0-9\s]/.test(inputField.value)) { // Notice the \s here
errorMessage += disallowedValue + '<br>'; // Add line break
}
});
errorBlock.innerHTML = errorMessage || ''; // Use innerHTML to interpret <br> tags
});
});
});
</script>
<!-- 💙 MEMBERSCRIPT #75 v0.1 💙 DISALOWED CHARACTER INPUTS -->
<script>
document.addEventListener('DOMContentLoaded', function() {
const inputFields = document.querySelectorAll('[ms-code-disallow]');
inputFields.forEach(inputField => {
const errorBlock = inputField.nextElementSibling;
errorBlock.innerHTML = ''; // Use innerHTML to interpret <br> tags
inputField.addEventListener('input', function() {
const rules = inputField.getAttribute('ms-code-disallow').split(')');
let errorMessage = '';
rules.forEach(rule => {
const parts = rule.trim().split('=');
const ruleType = parts[0].substring(1); // Remove the opening parenthesis
const disallowedValue = parts[1];
if (ruleType.startsWith('custom')) {
const disallowedChar = ruleType.split('-')[1]; // Extract the character after the '-'
if (inputField.value.includes(disallowedChar)) {
errorMessage += disallowedValue + '<br>'; // Add line break
}
} else if (ruleType === 'space' && inputField.value.includes(' ')) {
errorMessage += disallowedValue + '<br>'; // Add line break
} else if (ruleType === 'number' && /\d/.test(inputField.value)) {
errorMessage += disallowedValue + '<br>'; // Add line break
} else if (ruleType === 'special' && /[^a-zA-Z0-9\s]/.test(inputField.value)) { // Notice the \s here
errorMessage += disallowedValue + '<br>'; // Add line break
}
});
errorBlock.innerHTML = errorMessage || ''; // Use innerHTML to interpret <br> tags
});
});
});
</script>

#74 - Styliser avec des paramètres de lien
Mise à jour du style de la page en fonction d'un paramètre de lien. Ex. ?ms-code-target=CLASSNAME&ms-code-style=display:block
<!-- 💙 MEMBERSCRIPT #74 v0.1 💙 UPDATE STYLING WITH LINK PARAMS -->
<script>
// Function to parse URL parameters
function getURLParameter(name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [null, ''])[1].replace(/\+/g, '%20')) || null;
}
// Function to apply styles
function applyStylesFromURL() {
const targetClass = getURLParameter('ms-code-target');
const rawStyles = getURLParameter('ms-code-style');
if (targetClass && rawStyles) {
const elements = document.querySelectorAll(`.${targetClass}`);
const styles = rawStyles.split(';').filter(style => style.trim() !== ''); // filter out any empty strings
styles.forEach(style => {
const [property, value] = style.split(':');
elements.forEach(element => {
element.style[property] = value;
});
});
}
}
// Call the function once the DOM is loaded
window.addEventListener('DOMContentLoaded', (event) => {
applyStylesFromURL();
});
</script>
<!-- 💙 MEMBERSCRIPT #74 v0.1 💙 UPDATE STYLING WITH LINK PARAMS -->
<script>
// Function to parse URL parameters
function getURLParameter(name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [null, ''])[1].replace(/\+/g, '%20')) || null;
}
// Function to apply styles
function applyStylesFromURL() {
const targetClass = getURLParameter('ms-code-target');
const rawStyles = getURLParameter('ms-code-style');
if (targetClass && rawStyles) {
const elements = document.querySelectorAll(`.${targetClass}`);
const styles = rawStyles.split(';').filter(style => style.trim() !== ''); // filter out any empty strings
styles.forEach(style => {
const [property, value] = style.split(':');
elements.forEach(element => {
element.style[property] = value;
});
});
}
}
// Call the function once the DOM is loaded
window.addEventListener('DOMContentLoaded', (event) => {
applyStylesFromURL();
});
</script>

#73 - Affichage de la date et de l'heure
Affiche l'heure actuelle, l'heure du jour, le jour, le mois ou l'année pour un utilisateur. Fonctionne si l'utilisateur est connecté ou déconnecté.
<!-- 💙 MEMBERSCRIPT #73 v0.1 💙 DATES AND TIMES -->
function getCurrentDateInfo(attribute) {
const now = new Date();
const options = { hour12: true };
switch(attribute) {
case "day":
return now.toLocaleDateString('en-US', { weekday: 'long' });
case "time":
return now.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true }).toLowerCase();
case "month":
return now.toLocaleDateString('en-US', { month: 'long' });
case "year":
return now.getFullYear().toString();
case "time-of-day":
const hour = now.getHours();
if (5 <= hour && hour < 12) return "morning";
if (12 <= hour && hour < 17) return "afternoon";
if (17 <= hour && hour < 21) return "evening";
return "night";
default:
return "Invalid attribute";
}
}
function updateDateInfoOnPage() {
const spanTags = document.querySelectorAll('span[ms-code-date]');
spanTags.forEach(tag => {
const attributeValue = tag.getAttribute('ms-code-date');
const dateInfo = getCurrentDateInfo(attributeValue);
tag.textContent = dateInfo;
});
}
// Call the function to update the content on the page
updateDateInfoOnPage();
</script>
<!-- 💙 MEMBERSCRIPT #73 v0.1 💙 DATES AND TIMES -->
function getCurrentDateInfo(attribute) {
const now = new Date();
const options = { hour12: true };
switch(attribute) {
case "day":
return now.toLocaleDateString('en-US', { weekday: 'long' });
case "time":
return now.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true }).toLowerCase();
case "month":
return now.toLocaleDateString('en-US', { month: 'long' });
case "year":
return now.getFullYear().toString();
case "time-of-day":
const hour = now.getHours();
if (5 <= hour && hour < 12) return "morning";
if (12 <= hour && hour < 17) return "afternoon";
if (17 <= hour && hour < 21) return "evening";
return "night";
default:
return "Invalid attribute";
}
}
function updateDateInfoOnPage() {
const spanTags = document.querySelectorAll('span[ms-code-date]');
spanTags.forEach(tag => {
const attributeValue = tag.getAttribute('ms-code-date');
const dateInfo = getCurrentDateInfo(attributeValue);
tag.textContent = dateInfo;
});
}
// Call the function to update the content on the page
updateDateInfoOnPage();
</script>

#72 - Valider les valeurs originales
N'autoriser l'envoi d'un formulaire que si la valeur d'entrée est originale (c'est-à-dire les noms d'utilisateur).
<!-- 💙 MEMBERSCRIPT #72 v0.1 💙 VALIDATE ORIGINAL VALUES -->
<style>
[ms-code-available="true"],
[ms-code-available="false"],
[ms-code-available="invalid"]{
display: none;
}
.disabled {
opacity: 0.5;
pointer-events: none;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
let input = document.querySelector('[ms-code-available="input"]');
let trueElement = document.querySelector('[ms-code-available="true"]');
let falseElement = document.querySelector('[ms-code-available="false"]');
let invalidElement = document.querySelector('[ms-code-available="invalid"]');
let listElements = Array.from(document.querySelectorAll('[ms-code-available="list"]'));
let submitButton = document.querySelector('[ms-code-available="submit"]');
function checkUsername() {
// Check if the input matches any of the list items
let isTaken = listElements.some(elem => elem.textContent.trim() === input.value.trim());
if (isTaken) {
trueElement.style.display = 'none';
falseElement.style.display = 'flex';
submitButton.classList.add('disabled'); // disable the button if username is taken
} else {
trueElement.style.display = 'flex';
falseElement.style.display = 'none';
submitButton.classList.remove('disabled');
}
}
input.addEventListener('input', function() {
// Display the invalid element if input length is between 1 and 3
if (input.value.length >= 1 && input.value.length <= 3) {
invalidElement.style.display = 'flex';
} else {
invalidElement.style.display = 'none';
}
// Add the .disabled class to the submit button if input is empty or less than 3 characters
if (input.value.length <= 3) {
submitButton.classList.add('disabled');
trueElement.style.display = 'none';
falseElement.style.display = 'none';
} else {
checkUsername();
}
});
});
</script>
<!-- 💙 MEMBERSCRIPT #72 v0.1 💙 VALIDATE ORIGINAL VALUES -->
<style>
[ms-code-available="true"],
[ms-code-available="false"],
[ms-code-available="invalid"]{
display: none;
}
.disabled {
opacity: 0.5;
pointer-events: none;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
let input = document.querySelector('[ms-code-available="input"]');
let trueElement = document.querySelector('[ms-code-available="true"]');
let falseElement = document.querySelector('[ms-code-available="false"]');
let invalidElement = document.querySelector('[ms-code-available="invalid"]');
let listElements = Array.from(document.querySelectorAll('[ms-code-available="list"]'));
let submitButton = document.querySelector('[ms-code-available="submit"]');
function checkUsername() {
// Check if the input matches any of the list items
let isTaken = listElements.some(elem => elem.textContent.trim() === input.value.trim());
if (isTaken) {
trueElement.style.display = 'none';
falseElement.style.display = 'flex';
submitButton.classList.add('disabled'); // disable the button if username is taken
} else {
trueElement.style.display = 'flex';
falseElement.style.display = 'none';
submitButton.classList.remove('disabled');
}
}
input.addEventListener('input', function() {
// Display the invalid element if input length is between 1 and 3
if (input.value.length >= 1 && input.value.length <= 3) {
invalidElement.style.display = 'flex';
} else {
invalidElement.style.display = 'none';
}
// Add the .disabled class to the submit button if input is empty or less than 3 characters
if (input.value.length <= 3) {
submitButton.classList.add('disabled');
trueElement.style.display = 'none';
falseElement.style.display = 'none';
} else {
checkUsername();
}
});
});
</script>

#71 - Redirection si certains champs sont vides
Rediriger un membre vers une page d'accueil si certains champs personnalisés sont vides.
<!-- 💙 MEMBERSCRIPT #71 v0.1 💙 REDIRECT IF FIELDS ARE EMPTY -->
<script>
document.addEventListener('DOMContentLoaded', async function() {
const memberstack = window.$memberstackDom;
const onboardingPageUrl = '/onboarding'; // replace
const customFieldKeys = 'custom-field-1,custom-field-2'; // replace
// No need to edit past this line
const member = await memberstack.getCurrentMember();
if (!member) {
return;
}
// If current page slug matches the redirect slug, exit the script
const currentPageSlug = window.location.pathname;
if (currentPageSlug === onboardingPageUrl) {
return;
}
async function checkOnboardingStatus() {
try {
const memberData = await memberstack.updateMember({});
const customFields = customFieldKeys.split(',');
for (let field of customFields) {
if (!memberData.data.customFields[field.trim()]) {
// Redirect to onboarding page if the custom field is empty
window.location.href = onboardingPageUrl;
return;
}
}
} catch (error) {
console.error(`Error in checkOnboardingStatus function: ${error}`);
}
}
// Check onboarding status and potentially redirect
checkOnboardingStatus().catch(error => {
console.error(`Error in MemberScript #71 initial functions: ${error}`);
});
});
</script>
<!-- 💙 MEMBERSCRIPT #71 v0.1 💙 REDIRECT IF FIELDS ARE EMPTY -->
<script>
document.addEventListener('DOMContentLoaded', async function() {
const memberstack = window.$memberstackDom;
const onboardingPageUrl = '/onboarding'; // replace
const customFieldKeys = 'custom-field-1,custom-field-2'; // replace
// No need to edit past this line
const member = await memberstack.getCurrentMember();
if (!member) {
return;
}
// If current page slug matches the redirect slug, exit the script
const currentPageSlug = window.location.pathname;
if (currentPageSlug === onboardingPageUrl) {
return;
}
async function checkOnboardingStatus() {
try {
const memberData = await memberstack.updateMember({});
const customFields = customFieldKeys.split(',');
for (let field of customFields) {
if (!memberData.data.customFields[field.trim()]) {
// Redirect to onboarding page if the custom field is empty
window.location.href = onboardingPageUrl;
return;
}
}
} catch (error) {
console.error(`Error in checkOnboardingStatus function: ${error}`);
}
}
// Check onboarding status and potentially redirect
checkOnboardingStatus().catch(error => {
console.error(`Error in MemberScript #71 initial functions: ${error}`);
});
});
</script>

#70 - Masquer les éléments anciens/vus du CMS
N'affichez que les éléments du CMS qui sont nouveaux pour un membre particulier. S'il l'a déjà vu, cachez-le.
<!-- 💙 MEMBERSCRIPT #70 v0.1 💙 HIDE OLD CMS ITEMS -->
<script>
document.addEventListener('DOMContentLoaded', async function() {
const memberstack = window.$memberstackDom;
// Only proceed if a member is found
const member = await memberstack.getCurrentMember();
if (!member) {
console.log('No member found in MemberScript #70, exiting script');
return;
}
async function getCmsItemsFromJson() {
try {
const memberData = await memberstack.getMemberJSON();
return memberData?.data?.cmsItems || [];
} catch (error) {
console.error(`Error in getCmsItemsFromJson function: ${error}`);
}
}
async function updateCmsItemsInJson(newCmsItems) {
try {
const memberData = await memberstack.getMemberJSON();
memberData.data = memberData.data || {};
memberData.data.cmsItems = newCmsItems;
console.log(`CMS items in JSON after update: ${JSON.stringify(newCmsItems)}`);
await memberstack.updateMemberJSON({ json: memberData.data });
} catch (error) {
console.error(`Error in updateCmsItemsInJson function: ${error}`);
}
}
async function hideSeenCmsItems() {
try {
const cmsItemsElements = document.querySelectorAll('[ms-code-cms-item]');
const cmsItemsFromJson = await getCmsItemsFromJson();
cmsItemsElements.forEach(element => {
const cmsValue = element.getAttribute('ms-code-cms-item');
if (cmsItemsFromJson.includes(cmsValue)) {
element.style.display = 'none';
} else {
cmsItemsFromJson.push(cmsValue);
}
});
// Update the CMS items in JSON after the checks
await updateCmsItemsInJson(cmsItemsFromJson);
} catch (error) {
console.error(`Error in hideSeenCmsItems function: ${error}`);
}
}
// Hide seen CMS items when the page loads
hideSeenCmsItems().catch(error => {
console.error(`Error in MemberScript #70 initial functions: ${error}`);
});
});
</script>
<!-- 💙 MEMBERSCRIPT #70 v0.1 💙 HIDE OLD CMS ITEMS -->
<script>
document.addEventListener('DOMContentLoaded', async function() {
const memberstack = window.$memberstackDom;
// Only proceed if a member is found
const member = await memberstack.getCurrentMember();
if (!member) {
console.log('No member found in MemberScript #70, exiting script');
return;
}
async function getCmsItemsFromJson() {
try {
const memberData = await memberstack.getMemberJSON();
return memberData?.data?.cmsItems || [];
} catch (error) {
console.error(`Error in getCmsItemsFromJson function: ${error}`);
}
}
async function updateCmsItemsInJson(newCmsItems) {
try {
const memberData = await memberstack.getMemberJSON();
memberData.data = memberData.data || {};
memberData.data.cmsItems = newCmsItems;
console.log(`CMS items in JSON after update: ${JSON.stringify(newCmsItems)}`);
await memberstack.updateMemberJSON({ json: memberData.data });
} catch (error) {
console.error(`Error in updateCmsItemsInJson function: ${error}`);
}
}
async function hideSeenCmsItems() {
try {
const cmsItemsElements = document.querySelectorAll('[ms-code-cms-item]');
const cmsItemsFromJson = await getCmsItemsFromJson();
cmsItemsElements.forEach(element => {
const cmsValue = element.getAttribute('ms-code-cms-item');
if (cmsItemsFromJson.includes(cmsValue)) {
element.style.display = 'none';
} else {
cmsItemsFromJson.push(cmsValue);
}
});
// Update the CMS items in JSON after the checks
await updateCmsItemsInJson(cmsItemsFromJson);
} catch (error) {
console.error(`Error in hideSeenCmsItems function: ${error}`);
}
}
// Hide seen CMS items when the page loads
hideSeenCmsItems().catch(error => {
console.error(`Error in MemberScript #70 initial functions: ${error}`);
});
});
</script>

#69 - Notifier les membres des nouveaux éléments de la CMS
Afficher un élément lorsqu'il y a de nouveaux éléments CMS.
<!-- 💙 MEMBERSCRIPT #69 v0.1 💙 DISPLAY ELEMENT IF NEW CMS ITEMS -->
<script>
document.addEventListener('DOMContentLoaded', async function() {
const memberstack = window.$memberstackDom;
// Set this variable to 'YES' or 'NO' depending on whether you want the UI to be displayed for new users
const displayForNewUsers = 'YES';
// Only proceed if a member is found
const member = await memberstack.getCurrentMember();
if (!member) {
console.log('No member found, exiting script');
return;
}
async function getUpdatesIDFromJson() {
try {
const memberData = await memberstack.getMemberJSON();
console.log(`Member data: ${JSON.stringify(memberData)}`);
return memberData?.data?.updatesID || '';
} catch (error) {
console.error(`Error in getUpdatesIDFromJson function: ${error}`);
}
}
async function updateUpdatesIDInJson(newUpdatesID) {
try {
const memberData = await memberstack.getMemberJSON();
memberData.data = memberData.data || {};
memberData.data.updatesID = newUpdatesID;
console.log(`Updates ID in JSON after update: ${newUpdatesID}`);
await memberstack.updateMemberJSON({ json: memberData.data });
} catch (error) {
console.error(`Error in updateUpdatesIDInJson function: ${error}`);
}
}
async function checkAndUpdateUI() {
try {
const element = document.querySelector('[ms-code-update-item]');
const cmsItem = element.textContent;
console.log(`CMS item: ${cmsItem}`);
// Get the current updates ID from JSON
const updatesIDFromJson = await getUpdatesIDFromJson();
console.log(`Updates ID from JSON: ${updatesIDFromJson}`);
// Check displayForNewUsers variable to decide behavior
if (displayForNewUsers === 'NO' && !updatesIDFromJson) {
console.log('Updates ID from JSON is undefined, null, or empty, not changing UI');
return;
}
if (cmsItem !== updatesIDFromJson) {
const uiElements = document.querySelectorAll('[ms-code-update-ui]');
uiElements.forEach(uiElement => {
uiElement.style.display = 'block';
uiElement.style.opacity = '1';
});
}
// Update the updates ID in JSON after the UI has been updated
await updateUpdatesIDInJson(cmsItem);
} catch (error) {
console.error(`Error in checkAndUpdateUI function: ${error}`);
}
}
// Check and update UI when the page loads
checkAndUpdateUI().catch(error => {
console.error(`Error in initial functions: ${error}`);
});
});
</script>
<!-- 💙 MEMBERSCRIPT #69 v0.1 💙 DISPLAY ELEMENT IF NEW CMS ITEMS -->
<script>
document.addEventListener('DOMContentLoaded', async function() {
const memberstack = window.$memberstackDom;
// Set this variable to 'YES' or 'NO' depending on whether you want the UI to be displayed for new users
const displayForNewUsers = 'YES';
// Only proceed if a member is found
const member = await memberstack.getCurrentMember();
if (!member) {
console.log('No member found, exiting script');
return;
}
async function getUpdatesIDFromJson() {
try {
const memberData = await memberstack.getMemberJSON();
console.log(`Member data: ${JSON.stringify(memberData)}`);
return memberData?.data?.updatesID || '';
} catch (error) {
console.error(`Error in getUpdatesIDFromJson function: ${error}`);
}
}
async function updateUpdatesIDInJson(newUpdatesID) {
try {
const memberData = await memberstack.getMemberJSON();
memberData.data = memberData.data || {};
memberData.data.updatesID = newUpdatesID;
console.log(`Updates ID in JSON after update: ${newUpdatesID}`);
await memberstack.updateMemberJSON({ json: memberData.data });
} catch (error) {
console.error(`Error in updateUpdatesIDInJson function: ${error}`);
}
}
async function checkAndUpdateUI() {
try {
const element = document.querySelector('[ms-code-update-item]');
const cmsItem = element.textContent;
console.log(`CMS item: ${cmsItem}`);
// Get the current updates ID from JSON
const updatesIDFromJson = await getUpdatesIDFromJson();
console.log(`Updates ID from JSON: ${updatesIDFromJson}`);
// Check displayForNewUsers variable to decide behavior
if (displayForNewUsers === 'NO' && !updatesIDFromJson) {
console.log('Updates ID from JSON is undefined, null, or empty, not changing UI');
return;
}
if (cmsItem !== updatesIDFromJson) {
const uiElements = document.querySelectorAll('[ms-code-update-ui]');
uiElements.forEach(uiElement => {
uiElement.style.display = 'block';
uiElement.style.opacity = '1';
});
}
// Update the updates ID in JSON after the UI has been updated
await updateUpdatesIDInJson(cmsItem);
} catch (error) {
console.error(`Error in checkAndUpdateUI function: ${error}`);
}
}
// Check and update UI when the page loads
checkAndUpdateUI().catch(error => {
console.error(`Error in initial functions: ${error}`);
});
});
</script>

#68 - Offrir une adhésion
Permettre aux membres d'acheter des cadeaux pour leurs amis et leur famille.

#67 - Pré-remplir le formulaire en fonction des paramètres de l'URL
Remplir facilement les entrées à l'aide de paramètres URL.
<!-- 💙 MEMBERSCRIPT #67 v0.1 💙 PREFILL INPUTS WITH URL PARAMETERS -->
<script>
// Function to get URL parameters
function getURLParams() {
const urlParams = new URLSearchParams(window.location.search);
return Object.fromEntries(urlParams.entries());
}
// Function to prefill inputs based on URL parameters
function prefillInputs() {
const urlParams = getURLParams();
const inputElements = document.querySelectorAll('[ms-code-prefill-param]');
inputElements.forEach((inputElement) => {
const paramKey = inputElement.getAttribute('ms-code-prefill-param');
if (paramKey && urlParams[paramKey]) {
inputElement.value = urlParams[paramKey];
}
});
}
// Call the function to prefill inputs when the page loads
prefillInputs();
</script>
<!-- 💙 MEMBERSCRIPT #67 v0.1 💙 PREFILL INPUTS WITH URL PARAMETERS -->
<script>
// Function to get URL parameters
function getURLParams() {
const urlParams = new URLSearchParams(window.location.search);
return Object.fromEntries(urlParams.entries());
}
// Function to prefill inputs based on URL parameters
function prefillInputs() {
const urlParams = getURLParams();
const inputElements = document.querySelectorAll('[ms-code-prefill-param]');
inputElements.forEach((inputElement) => {
const paramKey = inputElement.getAttribute('ms-code-prefill-param');
if (paramKey && urlParams[paramKey]) {
inputElement.value = urlParams[paramKey];
}
});
}
// Call the function to prefill inputs when the page loads
prefillInputs();
</script>

#66 - Liens d'invitation pour l'identification des membres
Créer des liens d'invitation/de référence personnalisés et uniques.
<!-- 💙 MEMBERSCRIPT #66 v0.1 💙 MEMBER ID INVITE LINKS -->
<script>
// Function to get the member ID from local storage
function getMemberIDFromLocalStorage() {
// Assuming "_ms-mem" is the key that holds the member object in local storage
const memberObject = JSON.parse(localStorage.getItem("_ms-mem"));
if (memberObject && memberObject.id) {
return memberObject.id;
}
return null;
}
// Function to update the invite link with the member ID as a URL parameter
function updateInviteLink() {
const inviteLinkElement = document.querySelector('[ms-code-invite-link]');
if (inviteLinkElement) {
const inviteLinkBase = inviteLinkElement.getAttribute('ms-code-invite-link');
const memberID = getMemberIDFromLocalStorage();
if (memberID) {
const inviteLinkWithID = `${inviteLinkBase}?inviteCode=${memberID}`;
inviteLinkElement.textContent = inviteLinkWithID;
inviteLinkElement.href = inviteLinkWithID; // If it's an anchor link
}
}
}
// Call the function to update the invite link when the page loads
updateInviteLink();
</script>
<!-- 💙 MEMBERSCRIPT #66 v0.1 💙 MEMBER ID INVITE LINKS -->
<script>
// Function to get the member ID from local storage
function getMemberIDFromLocalStorage() {
// Assuming "_ms-mem" is the key that holds the member object in local storage
const memberObject = JSON.parse(localStorage.getItem("_ms-mem"));
if (memberObject && memberObject.id) {
return memberObject.id;
}
return null;
}
// Function to update the invite link with the member ID as a URL parameter
function updateInviteLink() {
const inviteLinkElement = document.querySelector('[ms-code-invite-link]');
if (inviteLinkElement) {
const inviteLinkBase = inviteLinkElement.getAttribute('ms-code-invite-link');
const memberID = getMemberIDFromLocalStorage();
if (memberID) {
const inviteLinkWithID = `${inviteLinkBase}?inviteCode=${memberID}`;
inviteLinkElement.textContent = inviteLinkWithID;
inviteLinkElement.href = inviteLinkWithID; // If it's an anchor link
}
}
}
// Call the function to update the invite link when the page loads
updateInviteLink();
</script>

#65 - Fenêtre contextuelle d'intention de sortie
Montrer aux visiteurs une fenêtre contextuelle lorsque leur souris quitte le haut de la page.
<!-- 💙 MEMBERSCRIPT #65 v0.1 💙 EXIT INTENT POPUP -->
<script>
const CookieService = {
setCookie(name, value, days) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
const expires = days ? '; expires=' + date.toUTCString() : '';
document.cookie = name + '=' + (value || '') + expires + ';';
},
getCookie(name) {
const cookieValue = document.cookie
.split('; ')
.find(row => row.startsWith(name))
?.split('=')[1];
return cookieValue || null;
}
};
const exitPopup = document.querySelector('[ms-code-popup="exit-intent"]');
const mouseEvent = e => {
const shouldShowExitIntent =
!e.toElement &&
!e.relatedTarget &&
e.clientY < 10;
if (shouldShowExitIntent) {
document.removeEventListener('mouseout', mouseEvent);
exitPopup.style.display = 'flex';
CookieService.setCookie('exitIntentShown', true, 30);
}
};
if (!CookieService.getCookie('exitIntentShown')) {
document.addEventListener('mouseout', mouseEvent);
document.addEventListener('keydown', exit);
exitPopup.addEventListener('click', exit);
}
</script>
<!-- 💙 MEMBERSCRIPT #65 v0.1 💙 EXIT INTENT POPUP -->
<script>
const CookieService = {
setCookie(name, value, days) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
const expires = days ? '; expires=' + date.toUTCString() : '';
document.cookie = name + '=' + (value || '') + expires + ';';
},
getCookie(name) {
const cookieValue = document.cookie
.split('; ')
.find(row => row.startsWith(name))
?.split('=')[1];
return cookieValue || null;
}
};
const exitPopup = document.querySelector('[ms-code-popup="exit-intent"]');
const mouseEvent = e => {
const shouldShowExitIntent =
!e.toElement &&
!e.relatedTarget &&
e.clientY < 10;
if (shouldShowExitIntent) {
document.removeEventListener('mouseout', mouseEvent);
exitPopup.style.display = 'flex';
CookieService.setCookie('exitIntentShown', true, 30);
}
};
if (!CookieService.getCookie('exitIntentShown')) {
document.addEventListener('mouseout', mouseEvent);
document.addEventListener('keydown', exit);
exitPopup.addEventListener('click', exit);
}
</script>

#64 - Logique du formulaire radio
Affiche les éléments du jeu en fonction de la radio sélectionnée.
<!-- 💙 MEMBERSCRIPT #64 v0.1 💙 RADIO FORM LOGIC -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
// initially hide all divs with 'ms-code-more-info' attribute
$("div[ms-code-more-info]").hide();
// listen for change events on all radios with 'ms-code-radio-option' attribute
$("input[ms-code-radio-option]").change(function() {
// hide all divs again
$("div[ms-code-more-info]").hide();
// get the value of the selected radio button
var selectedValue = $(this).attr("ms-code-radio-option");
// find the div with the 'ms-code-more-info' attribute that matches the selected value and show it
$("div[ms-code-more-info=" + selectedValue + "]").show();
});
});
</script>
<!-- 💙 MEMBERSCRIPT #64 v0.1 💙 RADIO FORM LOGIC -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
// initially hide all divs with 'ms-code-more-info' attribute
$("div[ms-code-more-info]").hide();
// listen for change events on all radios with 'ms-code-radio-option' attribute
$("input[ms-code-radio-option]").change(function() {
// hide all divs again
$("div[ms-code-more-info]").hide();
// get the value of the selected radio button
var selectedValue = $(this).attr("ms-code-radio-option");
// find the div with the 'ms-code-more-info' attribute that matches the selected value and show it
$("div[ms-code-more-info=" + selectedValue + "]").show();
});
});
</script>

#63 - Sélecteur d'intervalle de dates
Créer une plage de dates dans Webflow !
<!-- 💙 MEMBERSCRIPT #62 v0.1 💙 DATE RANGE PICKER -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css" />
<style>
.daterangepicker td.active {
background-color: #006cfa !important ;
}
</style>
<script type="text/javascript">
$(function() {
$('input[ms-code-input="date-range"]').daterangepicker({
"opens": "center",
"locale": {
"format": "MM/DD/YYYY",
"separator": " - ",
"applyLabel": "Apply",
"cancelLabel": "Cancel",
"fromLabel": "From",
"toLabel": "To",
"customRangeLabel": "Custom",
"weekLabel": "W",
"daysOfWeek": [
"Su",
"Mo",
"Tu",
"We",
"Th",
"Fr",
"Sa"
],
"monthNames": [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
],
},
});
$('input[name="datefilter"]').on('apply.daterangepicker', function(ev, picker) {
$(this).val(picker.startDate.format('MM/DD/YYYY') + ' - ' + picker.endDate.format('MM/DD/YYYY'));
});
$('input[name="datefilter"]').on('cancel.daterangepicker', function(ev, picker) {
$(this).val('');
});
});
</script>
<!-- 💙 MEMBERSCRIPT #62 v0.1 💙 DATE RANGE PICKER -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css" />
<style>
.daterangepicker td.active {
background-color: #006cfa !important ;
}
</style>
<script type="text/javascript">
$(function() {
$('input[ms-code-input="date-range"]').daterangepicker({
"opens": "center",
"locale": {
"format": "MM/DD/YYYY",
"separator": " - ",
"applyLabel": "Apply",
"cancelLabel": "Cancel",
"fromLabel": "From",
"toLabel": "To",
"customRangeLabel": "Custom",
"weekLabel": "W",
"daysOfWeek": [
"Su",
"Mo",
"Tu",
"We",
"Th",
"Fr",
"Sa"
],
"monthNames": [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
],
},
});
$('input[name="datefilter"]').on('apply.daterangepicker', function(ev, picker) {
$(this).val(picker.startDate.format('MM/DD/YYYY') + ' - ' + picker.endDate.format('MM/DD/YYYY'));
});
$('input[name="datefilter"]').on('cancel.daterangepicker', function(ev, picker) {
$(this).val('');
});
});
</script>

#62 - Bouton "Upvote
Ajouter la fonctionnalité "upvote" au CMS Webflow.
<!-- 💙 MEMBERSCRIPT #62 v0.2 💙 UPVOTE FORM -->
<script>
document.addEventListener('DOMContentLoaded', function() {
const memberstack = window.$memberstackDom;
const upvoteButtons = document.querySelectorAll('[ms-code="upvote-button"]');
const upvoteForms = document.querySelectorAll('[ms-code="upvote-form"]');
const upvotedValues = document.querySelectorAll('[ms-code="upvoted-value"]');
const upvoteCounts = document.querySelectorAll('[ms-code="upvote-count"]');
let clickTimeout; // Variable to store the timer
let lastClickedButton = null; // Variable to store the last clicked button
// Function to handle upvote button click
function handleUpvoteButtonClick(event) {
event.preventDefault();
const button = event.currentTarget;
// Clear the timer if the same button is clicked
if (button === lastClickedButton) {
clearTimeout(clickTimeout);
}
lastClickedButton = button; // Store the reference to the currently clicked button
// Set a new timer
clickTimeout = setTimeout(function() {
const form = button.closest('form');
const cmsId = button.getAttribute('data-cms-id');
const upvotedValue = form.querySelector('[ms-code="upvoted-value"]');
const upvoteCount = form.querySelector('[ms-code="upvote-count"]');
if (button.classList.contains('is-true')) {
// Remove upvote
button.classList.remove('is-true');
upvotedValue.value = 'false';
upvoteCount.textContent = parseInt(upvoteCount.textContent) - 1;
memberstack.getMemberJSON()
.then(function(memberData) {
if (memberData.data && memberData.data.upvotes) {
const upvotes = memberData.data.upvotes;
const index = upvotes.indexOf(cmsId);
if (index !== -1) {
upvotes.splice(index, 1);
memberstack.updateMemberJSON({ json: memberData.data });
}
}
})
.catch(function(error) {
console.error('Error retrieving/updating member data:', error);
});
} else {
// Add upvote
button.classList.add('is-true');
upvotedValue.value = 'true';
upvoteCount.textContent = parseInt(upvoteCount.textContent) + 1;
memberstack.getMemberJSON()
.then(function(memberData) {
memberData.data = memberData.data || {};
memberData.data.upvotes = memberData.data.upvotes || [];
memberData.data.upvotes.push(cmsId);
memberstack.updateMemberJSON({ json: memberData.data });
})
.catch(function(error) {
console.error('Error retrieving/updating member data:', error);
});
}
// Make the API call
fetch(form.action, {
method: form.method,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams(new FormData(form))
})
.then(function(response) {
if (response.ok) {
// Handle successful API response
return response.json();
} else {
// Handle API error
throw new Error('API Error');
}
})
.then(function(data) {
// Handle API response to update vote count
upvoteCount.textContent = data.upvoteCount; // Replace with the actual property holding the updated vote count
})
.catch(function(error) {
console.error('API Error:', error);
});
}, 200); // 0.2 seconds
}
// Attach event listeners to upvote buttons
upvoteButtons.forEach(function(button) {
button.addEventListener('click', handleUpvoteButtonClick);
});
// Check if member has upvotes on page load
memberstack.getMemberJSON()
.then(function(memberData) {
if (memberData.data && memberData.data.upvotes) {
const upvotes = memberData.data.upvotes;
upvoteButtons.forEach(function(button) {
const cmsId = button.getAttribute('data-cms-id');
if (upvotes.includes(cmsId)) {
button.classList.add('is-true');
const form = button.closest('form');
const upvotedValue = form.querySelector('[ms-code="upvoted-value"]');
upvotedValue.value = 'true';
}
});
}
})
.catch(function(error) {
console.error('Error retrieving member data:', error);
});
});
</script>
<!-- 💙 MEMBERSCRIPT #62 v0.2 💙 UPVOTE FORM -->
<script>
document.addEventListener('DOMContentLoaded', function() {
const memberstack = window.$memberstackDom;
const upvoteButtons = document.querySelectorAll('[ms-code="upvote-button"]');
const upvoteForms = document.querySelectorAll('[ms-code="upvote-form"]');
const upvotedValues = document.querySelectorAll('[ms-code="upvoted-value"]');
const upvoteCounts = document.querySelectorAll('[ms-code="upvote-count"]');
let clickTimeout; // Variable to store the timer
let lastClickedButton = null; // Variable to store the last clicked button
// Function to handle upvote button click
function handleUpvoteButtonClick(event) {
event.preventDefault();
const button = event.currentTarget;
// Clear the timer if the same button is clicked
if (button === lastClickedButton) {
clearTimeout(clickTimeout);
}
lastClickedButton = button; // Store the reference to the currently clicked button
// Set a new timer
clickTimeout = setTimeout(function() {
const form = button.closest('form');
const cmsId = button.getAttribute('data-cms-id');
const upvotedValue = form.querySelector('[ms-code="upvoted-value"]');
const upvoteCount = form.querySelector('[ms-code="upvote-count"]');
if (button.classList.contains('is-true')) {
// Remove upvote
button.classList.remove('is-true');
upvotedValue.value = 'false';
upvoteCount.textContent = parseInt(upvoteCount.textContent) - 1;
memberstack.getMemberJSON()
.then(function(memberData) {
if (memberData.data && memberData.data.upvotes) {
const upvotes = memberData.data.upvotes;
const index = upvotes.indexOf(cmsId);
if (index !== -1) {
upvotes.splice(index, 1);
memberstack.updateMemberJSON({ json: memberData.data });
}
}
})
.catch(function(error) {
console.error('Error retrieving/updating member data:', error);
});
} else {
// Add upvote
button.classList.add('is-true');
upvotedValue.value = 'true';
upvoteCount.textContent = parseInt(upvoteCount.textContent) + 1;
memberstack.getMemberJSON()
.then(function(memberData) {
memberData.data = memberData.data || {};
memberData.data.upvotes = memberData.data.upvotes || [];
memberData.data.upvotes.push(cmsId);
memberstack.updateMemberJSON({ json: memberData.data });
})
.catch(function(error) {
console.error('Error retrieving/updating member data:', error);
});
}
// Make the API call
fetch(form.action, {
method: form.method,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams(new FormData(form))
})
.then(function(response) {
if (response.ok) {
// Handle successful API response
return response.json();
} else {
// Handle API error
throw new Error('API Error');
}
})
.then(function(data) {
// Handle API response to update vote count
upvoteCount.textContent = data.upvoteCount; // Replace with the actual property holding the updated vote count
})
.catch(function(error) {
console.error('API Error:', error);
});
}, 200); // 0.2 seconds
}
// Attach event listeners to upvote buttons
upvoteButtons.forEach(function(button) {
button.addEventListener('click', handleUpvoteButtonClick);
});
// Check if member has upvotes on page load
memberstack.getMemberJSON()
.then(function(memberData) {
if (memberData.data && memberData.data.upvotes) {
const upvotes = memberData.data.upvotes;
upvoteButtons.forEach(function(button) {
const cmsId = button.getAttribute('data-cms-id');
if (upvotes.includes(cmsId)) {
button.classList.add('is-true');
const form = button.closest('form');
const upvotedValue = form.querySelector('[ms-code="upvoted-value"]');
upvotedValue.value = 'true';
}
});
}
})
.catch(function(error) {
console.error('Error retrieving member data:', error);
});
});
</script>

#61 - Affichage de l'élément si la case est cochée
Créer une visibilité conditionnelle basée sur un champ de type case à cocher.
<!-- 💙 MEMBERSCRIPT #61 v0.1 💙 SHOW ELEMENT IF CHECKBOX IS CHECKED -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"> </script>
<script>
$(document).ready(function() {
// Initially hide all elements with the 'ms-code-checkbox-display' attribute
$("[ms-code-checkbox-display]").hide();
// When a checkbox with 'ms-code-checkbox-input' attribute is clicked, perform the following
$("[ms-code-checkbox-input]").click(function() {
// Get the value of the 'ms-code-checkbox-input' attribute
var checkboxVal = $(this).attr('ms-code-checkbox-input');
// Find the corresponding element with the 'ms-code-checkbox-display' attribute and same value
var displayElement = $("[ms-code-checkbox-display=" + checkboxVal + "]");
// If this checkbox is checked, show the corresponding element
if ($(this).is(":checked")) {
displayElement.show();
} else {
// If this checkbox is unchecked, hide the corresponding element
displayElement.hide();
}
});
});
</script>
<!-- 💙 MEMBERSCRIPT #61 v0.1 💙 SHOW ELEMENT IF CHECKBOX IS CHECKED -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"> </script>
<script>
$(document).ready(function() {
// Initially hide all elements with the 'ms-code-checkbox-display' attribute
$("[ms-code-checkbox-display]").hide();
// When a checkbox with 'ms-code-checkbox-input' attribute is clicked, perform the following
$("[ms-code-checkbox-input]").click(function() {
// Get the value of the 'ms-code-checkbox-input' attribute
var checkboxVal = $(this).attr('ms-code-checkbox-input');
// Find the corresponding element with the 'ms-code-checkbox-display' attribute and same value
var displayElement = $("[ms-code-checkbox-display=" + checkboxVal + "]");
// If this checkbox is checked, show the corresponding element
if ($(this).is(":checked")) {
displayElement.show();
} else {
// If this checkbox is unchecked, hide the corresponding element
displayElement.hide();
}
});
});
</script>

#60 - Augmentation/diminution de la valeur de sélection
Créer des boutons précédent et suivant pour un champ de sélection.
<!-- 💙 MEMBERSCRIPT #60 v0.1 💙 INCREASE/DECREASE SELECT VALUE -->
<script>
var select = document.querySelector('[ms-code-select="input"]');
var prev = document.querySelector('[ms-code-select="prev"]');
var next = document.querySelector('[ms-code-select="next"]');
function updateButtons() {
prev.style.opacity = select.selectedIndex === 0 ? '0.5' : '1';
next.style.opacity = select.selectedIndex === select.options.length - 1 ? '0.5' : '1';
}
prev.addEventListener('click', function() {
if (select.selectedIndex > 0) {
select.selectedIndex--;
}
updateButtons();
});
next.addEventListener('click', function() {
if (select.selectedIndex < select.options.length - 1) {
select.selectedIndex++;
}
updateButtons();
});
updateButtons();
</script>
<!-- 💙 MEMBERSCRIPT #60 v0.1 💙 INCREASE/DECREASE SELECT VALUE -->
<script>
var select = document.querySelector('[ms-code-select="input"]');
var prev = document.querySelector('[ms-code-select="prev"]');
var next = document.querySelector('[ms-code-select="next"]');
function updateButtons() {
prev.style.opacity = select.selectedIndex === 0 ? '0.5' : '1';
next.style.opacity = select.selectedIndex === select.options.length - 1 ? '0.5' : '1';
}
prev.addEventListener('click', function() {
if (select.selectedIndex > 0) {
select.selectedIndex--;
}
updateButtons();
});
next.addEventListener('click', function() {
if (select.selectedIndex < select.options.length - 1) {
select.selectedIndex++;
}
updateButtons();
});
updateButtons();
</script>

#59 - Redémarrer le GIF au survol de la page
Commencer un GIF depuis le début au survol de la page.
<!-- 💙 MEMBERSCRIPT #59 v0.1 💙 RESTART GIF -->
<script>
document.addEventListener('DOMContentLoaded', (event) => {
const hoverElements = document.querySelectorAll('[data-gif-hover]');
hoverElements.forEach((element) => {
element.addEventListener('mouseover', function() {
const gifNum = this.getAttribute('data-gif-hover');
const gifElement = document.querySelector(`[data-gif="${gifNum}"]`);
if (gifElement) {
const gifSrc = gifElement.getAttribute('src');
gifElement.setAttribute('src', '');
gifElement.setAttribute('src', gifSrc);
}
});
});
});
</script>
<!-- 💙 MEMBERSCRIPT #59 v0.1 💙 RESTART GIF -->
<script>
document.addEventListener('DOMContentLoaded', (event) => {
const hoverElements = document.querySelectorAll('[data-gif-hover]');
hoverElements.forEach((element) => {
element.addEventListener('mouseover', function() {
const gifNum = this.getAttribute('data-gif-hover');
const gifElement = document.querySelector(`[data-gif="${gifNum}"]`);
if (gifElement) {
const gifSrc = gifElement.getAttribute('src');
gifElement.setAttribute('src', '');
gifElement.setAttribute('src', gifSrc);
}
});
});
});
</script>
Scripts des membres
Instantly add custom features to your Webflow site.
Just paste a script, set attributes, and go live.
Join the Memberstack 2.0 Slack for tips, answers, and community scripts. Please note that these are not official features and support cannot be guaranteed.

#17 - Création d'un lien à partir d'un champ personnalisé
Utilisez des champs personnalisés pour remplir les cibles de liens avec un seul attribut !
<!-- 💙 MEMBERSCRIPT #17 v0.3 💙 ADD CUSTOM FIELD AS A LINK -->
<script>
document.addEventListener("DOMContentLoaded", function() {
const memberData = JSON.parse(localStorage.getItem('_ms-mem') || '{}');
if (!memberData?.id) return;
document.querySelectorAll('[ms-code-field-link]').forEach(element => {
const fieldKey = element.getAttribute('ms-code-field-link');
const fieldValue = memberData.customFields?.[fieldKey]?.trim();
if (!fieldValue) {
element.style.display = 'none';
return;
}
try {
// Add protocol if missing and validate URL
const url = !/^https?:\/\//i.test(fieldValue) ? 'https://' + fieldValue : fieldValue;
new URL(url); // Will throw if invalid URL
element.href = url;
element.rel = 'noopener noreferrer';
element.target = '_blank';
} catch {
element.style.display = 'none';
}
});
});
</script>
<!-- 💙 MEMBERSCRIPT #17 v0.3 💙 ADD CUSTOM FIELD AS A LINK -->
<script>
document.addEventListener("DOMContentLoaded", function() {
const memberData = JSON.parse(localStorage.getItem('_ms-mem') || '{}');
if (!memberData?.id) return;
document.querySelectorAll('[ms-code-field-link]').forEach(element => {
const fieldKey = element.getAttribute('ms-code-field-link');
const fieldValue = memberData.customFields?.[fieldKey]?.trim();
if (!fieldValue) {
element.style.display = 'none';
return;
}
try {
// Add protocol if missing and validate URL
const url = !/^https?:\/\//i.test(fieldValue) ? 'https://' + fieldValue : fieldValue;
new URL(url); // Will throw if invalid URL
element.href = url;
element.rel = 'noopener noreferrer';
element.target = '_blank';
} catch {
element.style.display = 'none';
}
});
});
</script>

#16 - Fin de la session après X minutes d'inactivité
Ce script redirige les utilisateurs inactifs vers une page "Session expirée" après une certaine période d'inactivité. Un compte à rebours est affiché sur la page et se réinitialise en fonction de l'activité de la page.
Add this code before the closing </body> tag any page which needs a countdown timer.
<!-- 💙 MEMBERSCRIPT #16 v0.2 💙 LOGOUT AFTER X MINUTES OF INACTIVITY -->
<script>
let logoutTimer;
let countdownInterval;
let initialTime;
function startLogoutTimer() {
// Get the logout time from the HTML element
const timeElement = document.querySelector('[ms-code-logout-timer]');
const timeParts = timeElement.textContent.split(':');
const minutes = parseInt(timeParts[0], 10);
const seconds = parseInt(timeParts[1], 10);
const LOGOUT_TIME = (minutes * 60 + seconds) * 1000; // Convert to milliseconds
// Store the initial time value
if (!initialTime) {
initialTime = LOGOUT_TIME;
}
// Clear the previous timer, if any
clearTimeout(logoutTimer);
clearInterval(countdownInterval);
let startTime = Date.now();
// Start a new timer to redirect the user after the specified time
logoutTimer = setTimeout(() => {
window.location.href = "/expired";
startLogoutTimer(); // Start the logout timer again
}, LOGOUT_TIME);
// Start a countdown timer
countdownInterval = setInterval(() => {
let elapsed = Date.now() - startTime;
let remaining = LOGOUT_TIME - elapsed;
updateCountdownDisplay(remaining);
}, 1000); // update every second
}
function updateCountdownDisplay(remainingTimeInMs) {
// convert ms to MM:SS format
let minutes = Math.floor(remainingTimeInMs / 1000 / 60);
let seconds = Math.floor((remainingTimeInMs / 1000) % 60);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
const timeElement = document.querySelector('[ms-code-logout-timer]');
timeElement.textContent = `${minutes}:${seconds}`;
}
// Call this function whenever the user interacts with the page
function resetLogoutTimer() {
const timeElement = document.querySelector('[ms-code-logout-timer]');
timeElement.textContent = formatTime(initialTime); // Reset to the initial time
startLogoutTimer();
}
function formatTime(timeInMs) {
let minutes = Math.floor(timeInMs / 1000 / 60);
let seconds = Math.floor((timeInMs / 1000) % 60);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
return `${minutes}:${seconds}`;
}
// Call this function when the user logs in
function cancelLogoutTimer() {
clearTimeout(logoutTimer);
clearInterval(countdownInterval);
}
// Start the timer when the page loads
startLogoutTimer();
// Add event listeners to reset timer on any page activity
document.addEventListener('mousemove', resetLogoutTimer);
document.addEventListener('keypress', resetLogoutTimer);
document.addEventListener('touchstart', resetLogoutTimer);
</script>
Add this code to your /expired page before the closing </body> tag.
<!-- 💙 MEMBERSCRIPT #16 v0.2 💙 LOGOUT AFTER X MINUTES OF INACTIVITY -->
<script>
window.addEventListener('load', () => {
window.$memberstackDom.getCurrentMember().then(async ({ data: member }) => {
if (member) {
try {
await window.$memberstackDom.logout();
console.log('Logged out successfully');
setTimeout(() => {
location.reload();
}, 1000); // Refresh the page 1 second after logout
} catch (error) {
console.error(error);
}
}
});
});
</script>
Add this code before the closing </body> tag any page which needs a countdown timer.
<!-- 💙 MEMBERSCRIPT #16 v0.2 💙 LOGOUT AFTER X MINUTES OF INACTIVITY -->
<script>
let logoutTimer;
let countdownInterval;
let initialTime;
function startLogoutTimer() {
// Get the logout time from the HTML element
const timeElement = document.querySelector('[ms-code-logout-timer]');
const timeParts = timeElement.textContent.split(':');
const minutes = parseInt(timeParts[0], 10);
const seconds = parseInt(timeParts[1], 10);
const LOGOUT_TIME = (minutes * 60 + seconds) * 1000; // Convert to milliseconds
// Store the initial time value
if (!initialTime) {
initialTime = LOGOUT_TIME;
}
// Clear the previous timer, if any
clearTimeout(logoutTimer);
clearInterval(countdownInterval);
let startTime = Date.now();
// Start a new timer to redirect the user after the specified time
logoutTimer = setTimeout(() => {
window.location.href = "/expired";
startLogoutTimer(); // Start the logout timer again
}, LOGOUT_TIME);
// Start a countdown timer
countdownInterval = setInterval(() => {
let elapsed = Date.now() - startTime;
let remaining = LOGOUT_TIME - elapsed;
updateCountdownDisplay(remaining);
}, 1000); // update every second
}
function updateCountdownDisplay(remainingTimeInMs) {
// convert ms to MM:SS format
let minutes = Math.floor(remainingTimeInMs / 1000 / 60);
let seconds = Math.floor((remainingTimeInMs / 1000) % 60);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
const timeElement = document.querySelector('[ms-code-logout-timer]');
timeElement.textContent = `${minutes}:${seconds}`;
}
// Call this function whenever the user interacts with the page
function resetLogoutTimer() {
const timeElement = document.querySelector('[ms-code-logout-timer]');
timeElement.textContent = formatTime(initialTime); // Reset to the initial time
startLogoutTimer();
}
function formatTime(timeInMs) {
let minutes = Math.floor(timeInMs / 1000 / 60);
let seconds = Math.floor((timeInMs / 1000) % 60);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
return `${minutes}:${seconds}`;
}
// Call this function when the user logs in
function cancelLogoutTimer() {
clearTimeout(logoutTimer);
clearInterval(countdownInterval);
}
// Start the timer when the page loads
startLogoutTimer();
// Add event listeners to reset timer on any page activity
document.addEventListener('mousemove', resetLogoutTimer);
document.addEventListener('keypress', resetLogoutTimer);
document.addEventListener('touchstart', resetLogoutTimer);
</script>
Add this code to your /expired page before the closing </body> tag.
<!-- 💙 MEMBERSCRIPT #16 v0.2 💙 LOGOUT AFTER X MINUTES OF INACTIVITY -->
<script>
window.addEventListener('load', () => {
window.$memberstackDom.getCurrentMember().then(async ({ data: member }) => {
if (member) {
try {
await window.$memberstackDom.logout();
console.log('Logged out successfully');
setTimeout(() => {
location.reload();
}, 1000); // Refresh the page 1 second after logout
} catch (error) {
console.error(error);
}
}
});
});
</script>

#15 - Rafraîchir la page après une durée définie au clic
Actualiser la page au bout d'un certain temps lorsqu'un élément est cliqué.
<!-- 💙 MEMBERSCRIPT #15 v0.1 💙 TRIGGER REFRESH ON CLICK -->
<script>
document.addEventListener("DOMContentLoaded", function() {
document.addEventListener("click", function(event) {
const clickedElement = event.target.closest('[ms-code-refresh]');
if (clickedElement) {
const refreshDelay = parseInt(clickedElement.getAttribute('ms-code-refresh'));
if (!isNaN(refreshDelay)) {
setTimeout(function() {
location.reload();
}, refreshDelay);
}
}
});
});
</script>
<!-- 💙 MEMBERSCRIPT #15 v0.1 💙 TRIGGER REFRESH ON CLICK -->
<script>
document.addEventListener("DOMContentLoaded", function() {
document.addEventListener("click", function(event) {
const clickedElement = event.target.closest('[ms-code-refresh]');
if (clickedElement) {
const refreshDelay = parseInt(clickedElement.getAttribute('ms-code-refresh'));
if (!isNaN(refreshDelay)) {
setTimeout(function() {
location.reload();
}, refreshDelay);
}
}
});
});
</script>

#14 - Créer un état de chargement au clic
Simuler un état de chargement personnalisé lorsqu'un élément est cliqué.
<!-- 💙 MEMBERSCRIPT #14 v0.1 💙 CREATE LOADING STATE ON CLICK -->
<script src="https://code.jquery.com/jquery-3.7.0.min.js" integrity="sha256-2Pmvv0kuTBOenSvLm6bvfBSSHrUJ+3A7x6P5Ebd07/g=" crossorigin="anonymous" ></script>
<script>
$(document).ready(function() {
// Bind click event to elements with ms-code-loading-trigger attribute
$(document).on('click', '[ms-code-loading-trigger]', function() {
// Get the value of ms-code-loading-trigger attribute
var triggerValue = $(this).attr("ms-code-loading-trigger");
// Find the matching loading element
var loadingElement = $("[ms-code-loading-element='" + triggerValue + "']");
// Find the matching subject element
var subjectElement = $("[ms-code-loading-subject='" + triggerValue + "']");
// Show the loading element (with flex display), append it to the subject element
loadingElement.css('display', 'flex').appendTo(subjectElement);
// After 5 seconds (5000 milliseconds), hide the loading element
setTimeout(function() {
loadingElement.hide();
}, 5000);
});
});
</script>
<!-- 💙 MEMBERSCRIPT #14 v0.1 💙 CREATE LOADING STATE ON CLICK -->
<script src="https://code.jquery.com/jquery-3.7.0.min.js" integrity="sha256-2Pmvv0kuTBOenSvLm6bvfBSSHrUJ+3A7x6P5Ebd07/g=" crossorigin="anonymous" ></script>
<script>
$(document).ready(function() {
// Bind click event to elements with ms-code-loading-trigger attribute
$(document).on('click', '[ms-code-loading-trigger]', function() {
// Get the value of ms-code-loading-trigger attribute
var triggerValue = $(this).attr("ms-code-loading-trigger");
// Find the matching loading element
var loadingElement = $("[ms-code-loading-element='" + triggerValue + "']");
// Find the matching subject element
var subjectElement = $("[ms-code-loading-subject='" + triggerValue + "']");
// Show the loading element (with flex display), append it to the subject element
loadingElement.css('display', 'flex').appendTo(subjectElement);
// After 5 seconds (5000 milliseconds), hide the loading element
setTimeout(function() {
loadingElement.hide();
}, 5000);
});
});
</script>

#13 - Filtrer les groupes d'éléments JSON
Affichez des listes filtrées à vos membres sur la base d'une propriété JSON !
<!-- 💙 MEMBERSCRIPT #13 v0.2 💙 FILTER ITEM GROUPS FROM JSON BASED ON ATTRIBUTE VALUE -->
<script>
(function() {
const memberstack = window.$memberstackDom;
let member;
const fetchMemberJSON = async function() {
member = await memberstack.getMemberJSON();
return member;
}
const filterItems = async function(printList) {
const filterAttr = printList.getAttribute('ms-code-list-filter');
if (!filterAttr) return;
const filters = filterAttr.split(',').map(filter => filter.trim());
const jsonGroup = printList.getAttribute('ms-code-print-list');
const items = member.data && member.data[jsonGroup] ? Object.values(member.data[jsonGroup]) : [];
const itemContainer = document.createElement('div');
const placeholder = printList.querySelector(`[ms-code-print-item="${jsonGroup}"]`);
const itemTemplate = placeholder.outerHTML;
items.forEach(item => {
const newItem = document.createElement('div');
newItem.innerHTML = itemTemplate;
const itemElements = newItem.querySelectorAll('[ms-code-item-text]');
let skipItem = false;
filters.forEach(filter => {
const exclude = filter.startsWith('!');
const filterKey = exclude ? filter.substring(1) : filter;
if ((exclude && item.hasOwnProperty(filterKey)) || (!exclude && !item.hasOwnProperty(filterKey))) {
skipItem = true;
}
});
if (skipItem) return; // Skip this item
itemElements.forEach(itemElement => {
const jsonKey = itemElement.getAttribute('ms-code-item-text');
const value = item && item[jsonKey] ? item[jsonKey] : '';
itemElement.textContent = value;
});
const itemKey = Object.keys(member.data[jsonGroup]).find(k => member.data[jsonGroup][k] === item);
newItem.firstChild.setAttribute('ms-code-item-key', itemKey);
itemContainer.appendChild(newItem.firstChild);
});
printList.innerHTML = itemContainer.innerHTML;
};
// Fetch member JSON
let intervalId = setInterval(async () => {
member = await fetchMemberJSON();
if (member && member.data) {
clearInterval(intervalId);
const printLists = document.querySelectorAll('[ms-code-print-list]');
printLists.forEach(filterItems);
}
}, 500);
// Add click event listener to elements with ms-code-update="json"
const updateButtons = document.querySelectorAll('[ms-code-update="json"]');
updateButtons.forEach(button => {
button.addEventListener("click", async function() {
// Fetch member JSON on each click
let intervalIdClick = setInterval(async () => {
member = await fetchMemberJSON();
if (member && member.data) {
clearInterval(intervalIdClick);
const printLists = document.querySelectorAll('[ms-code-print-list]');
printLists.forEach(filterItems);
}
}, 500);
});
});
})();
</script>
<!-- 💙 MEMBERSCRIPT #13 v0.2 💙 FILTER ITEM GROUPS FROM JSON BASED ON ATTRIBUTE VALUE -->
<script>
(function() {
const memberstack = window.$memberstackDom;
let member;
const fetchMemberJSON = async function() {
member = await memberstack.getMemberJSON();
return member;
}
const filterItems = async function(printList) {
const filterAttr = printList.getAttribute('ms-code-list-filter');
if (!filterAttr) return;
const filters = filterAttr.split(',').map(filter => filter.trim());
const jsonGroup = printList.getAttribute('ms-code-print-list');
const items = member.data && member.data[jsonGroup] ? Object.values(member.data[jsonGroup]) : [];
const itemContainer = document.createElement('div');
const placeholder = printList.querySelector(`[ms-code-print-item="${jsonGroup}"]`);
const itemTemplate = placeholder.outerHTML;
items.forEach(item => {
const newItem = document.createElement('div');
newItem.innerHTML = itemTemplate;
const itemElements = newItem.querySelectorAll('[ms-code-item-text]');
let skipItem = false;
filters.forEach(filter => {
const exclude = filter.startsWith('!');
const filterKey = exclude ? filter.substring(1) : filter;
if ((exclude && item.hasOwnProperty(filterKey)) || (!exclude && !item.hasOwnProperty(filterKey))) {
skipItem = true;
}
});
if (skipItem) return; // Skip this item
itemElements.forEach(itemElement => {
const jsonKey = itemElement.getAttribute('ms-code-item-text');
const value = item && item[jsonKey] ? item[jsonKey] : '';
itemElement.textContent = value;
});
const itemKey = Object.keys(member.data[jsonGroup]).find(k => member.data[jsonGroup][k] === item);
newItem.firstChild.setAttribute('ms-code-item-key', itemKey);
itemContainer.appendChild(newItem.firstChild);
});
printList.innerHTML = itemContainer.innerHTML;
};
// Fetch member JSON
let intervalId = setInterval(async () => {
member = await fetchMemberJSON();
if (member && member.data) {
clearInterval(intervalId);
const printLists = document.querySelectorAll('[ms-code-print-list]');
printLists.forEach(filterItems);
}
}, 500);
// Add click event listener to elements with ms-code-update="json"
const updateButtons = document.querySelectorAll('[ms-code-update="json"]');
updateButtons.forEach(button => {
button.addEventListener("click", async function() {
// Fetch member JSON on each click
let intervalIdClick = setInterval(async () => {
member = await fetchMemberJSON();
if (member && member.data) {
clearInterval(intervalIdClick);
const printLists = document.querySelectorAll('[ms-code-print-list]');
printLists.forEach(filterItems);
}
}, 500);
});
});
})();
</script>

#12 - Ajouter des éléments à des groupes JSON sur simple clic
Ajoutez un élément/une propriété aux éléments JSON précédemment créés en un seul clic !
<!-- 💙 MEMBERSCRIPT #12 v0.1 💙 ADD ITEM TO JSON GROUP ON CLICK -->
<script>
document.addEventListener("DOMContentLoaded", function() {
const memberstack = window.$memberstackDom;
// Add click event listener to the document
document.addEventListener("click", async function(event) {
const target = event.target;
// Check if the clicked element has ms-code-update-json-item attribute
const updateJsonItem = target.closest('[ms-code-update-json-item]');
if (updateJsonItem) {
const key = updateJsonItem.closest('[ms-code-item-key]').getAttribute('ms-code-item-key');
const jsonGroup = updateJsonItem.closest('[ms-code-print-list]').getAttribute('ms-code-print-list');
// Retrieve the current member JSON data
const member = await memberstack.getMemberJSON();
if (member.data && member.data[jsonGroup] && member.data[jsonGroup][key]) {
// Get the value to be added to the item in the member JSON
const updateValue = updateJsonItem.getAttribute('ms-code-update-json-item');
// Update the member JSON with the new value
member.data[jsonGroup][key][updateValue] = true;
// Update the member JSON using the Memberstack SDK
await memberstack.updateMemberJSON({
json: member.data
});
// Optional: Display a success message or perform any other desired action
console.log('Member JSON updated successfully');
} else {
console.error(`Could not find item with key: ${key}`);
}
}
// Check if the clicked element has ms-code-update attribute
const updateButton = target.closest('[ms-code-update="json"]');
if (updateButton) {
// Add a delay
await new Promise(resolve => setTimeout(resolve, 500));
// Retrieve the current member JSON data
const member = await memberstack.getMemberJSON();
// Save the member JSON as a local storage item
localStorage.setItem("memberJSON", JSON.stringify(member));
// Optional: Display a success message or perform any other desired action
console.log('Member JSON saved to local storage');
}
});
});
</script>
<!-- 💙 MEMBERSCRIPT #12 v0.1 💙 ADD ITEM TO JSON GROUP ON CLICK -->
<script>
document.addEventListener("DOMContentLoaded", function() {
const memberstack = window.$memberstackDom;
// Add click event listener to the document
document.addEventListener("click", async function(event) {
const target = event.target;
// Check if the clicked element has ms-code-update-json-item attribute
const updateJsonItem = target.closest('[ms-code-update-json-item]');
if (updateJsonItem) {
const key = updateJsonItem.closest('[ms-code-item-key]').getAttribute('ms-code-item-key');
const jsonGroup = updateJsonItem.closest('[ms-code-print-list]').getAttribute('ms-code-print-list');
// Retrieve the current member JSON data
const member = await memberstack.getMemberJSON();
if (member.data && member.data[jsonGroup] && member.data[jsonGroup][key]) {
// Get the value to be added to the item in the member JSON
const updateValue = updateJsonItem.getAttribute('ms-code-update-json-item');
// Update the member JSON with the new value
member.data[jsonGroup][key][updateValue] = true;
// Update the member JSON using the Memberstack SDK
await memberstack.updateMemberJSON({
json: member.data
});
// Optional: Display a success message or perform any other desired action
console.log('Member JSON updated successfully');
} else {
console.error(`Could not find item with key: ${key}`);
}
}
// Check if the clicked element has ms-code-update attribute
const updateButton = target.closest('[ms-code-update="json"]');
if (updateButton) {
// Add a delay
await new Promise(resolve => setTimeout(resolve, 500));
// Retrieve the current member JSON data
const member = await memberstack.getMemberJSON();
// Save the member JSON as a local storage item
localStorage.setItem("memberJSON", JSON.stringify(member));
// Optional: Display a success message or perform any other desired action
console.log('Member JSON saved to local storage');
}
});
});
</script>

#11 - Ouvrir automatiquement la fenêtre modale de connexion
Montrer à tous les visiteurs déconnectés une fenêtre modale de connexion immédiatement après la visite de la page. Les Memberstack personnalisés et par défaut fonctionnent.
<!-- 💙 MEMBERSCRIPT #11 v0.1 💙 SHOW LOGIN MODAL IF MEMBER IS NOT LOGGED IN -->
<!-- KEEP THIS FOR DEFAULT MEMBERSTACK MODAL -->
<script>
function handleRedirect(redirect) {
if (redirect && (window.location.pathname !== redirect)) return window.location.href = redirect;
window.location.reload()
}
$memberstackDom.getCurrentMember().then(async ({
data
}) => {
if (!data) {
const {
data
} = await $memberstackDom.openModal("login");
handleRedirect(data.redirect)
}
})
</script>
<!-- KEEP THIS FOR YOUR OWN CUSTOM MODAL -->
<script>
$memberstackDom.getCurrentMember().then(({ data }) => {
if (!data) {
const loginModal = document.querySelector('[ms-code-modal="login"]');
if (loginModal) {
loginModal.style.display = "flex";
}
}
});
</script>
<!-- 💙 MEMBERSCRIPT #11 v0.1 💙 SHOW LOGIN MODAL IF MEMBER IS NOT LOGGED IN -->
<!-- KEEP THIS FOR DEFAULT MEMBERSTACK MODAL -->
<script>
function handleRedirect(redirect) {
if (redirect && (window.location.pathname !== redirect)) return window.location.href = redirect;
window.location.reload()
}
$memberstackDom.getCurrentMember().then(async ({
data
}) => {
if (!data) {
const {
data
} = await $memberstackDom.openModal("login");
handleRedirect(data.redirect)
}
})
</script>
<!-- KEEP THIS FOR YOUR OWN CUSTOM MODAL -->
<script>
$memberstackDom.getCurrentMember().then(({ data }) => {
if (!data) {
const loginModal = document.querySelector('[ms-code-modal="login"]');
if (loginModal) {
loginModal.style.display = "flex";
}
}
});
</script>

#10 - Afficher/supprimer un élément en fonction d'un champ personnalisé
Vérifier si un membre a rempli un champ personnalisé. Si c'est le cas, l'élément cible est affiché.
<!-- 💙 MEMBERSCRIPT #10 v0.2 💙 HIDE ELEMENTS IF CUSTOM FIELD IS BLANK -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// Get the `_ms-mem` object from the local storage
const msMem = JSON.parse(localStorage.getItem('_ms-mem'));
// Get all the elements that have the `ms-code-customfield` attribute
const elements = document.querySelectorAll('[ms-code-customfield]');
// Iterate over each element
elements.forEach(element => {
// Get the value of the `ms-code-customfield` attribute
const customField = element.getAttribute('ms-code-customfield');
// If customField starts with '!', we invert the logic
if (customField.startsWith('!')) {
const actualCustomField = customField.slice(1); // remove the '!' from the start
// If the custom field is empty, remove the element from the DOM
if (msMem.customFields && msMem.customFields[actualCustomField]) {
element.parentNode.removeChild(element);
}
} else {
// Check if the user has the corresponding custom field in Memberstack
if (!msMem.customFields || !msMem.customFields[customField]) {
// If the custom field is empty, remove the element from the DOM
element.parentNode.removeChild(element);
}
}
});
});
</script>
<!-- 💙 MEMBERSCRIPT #10 v0.2 💙 HIDE ELEMENTS IF CUSTOM FIELD IS BLANK -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// Get the `_ms-mem` object from the local storage
const msMem = JSON.parse(localStorage.getItem('_ms-mem'));
// Get all the elements that have the `ms-code-customfield` attribute
const elements = document.querySelectorAll('[ms-code-customfield]');
// Iterate over each element
elements.forEach(element => {
// Get the value of the `ms-code-customfield` attribute
const customField = element.getAttribute('ms-code-customfield');
// If customField starts with '!', we invert the logic
if (customField.startsWith('!')) {
const actualCustomField = customField.slice(1); // remove the '!' from the start
// If the custom field is empty, remove the element from the DOM
if (msMem.customFields && msMem.customFields[actualCustomField]) {
element.parentNode.removeChild(element);
}
} else {
// Check if the user has the corresponding custom field in Memberstack
if (!msMem.customFields || !msMem.customFields[customField]) {
// If the custom field is empty, remove the element from the DOM
element.parentNode.removeChild(element);
}
}
});
});
</script>

#9 - Compte à rebours réel, basé sur l'utilisateur
Définir dynamiquement un compte à rebours par utilisateur et masquer les éléments lorsque le temps est écoulé.
<!-- 💙 MEMBERSCRIPT #9 v0.1 💙 COUNTDOWN BY USER -->
<script>
// Step 1: Get the current date and time
const currentDate = new Date();
// Step 2: Calculate the new date and time based on the attribute values
const addTime = (date, unit, value) => {
const newDate = new Date(date);
switch (unit) {
case 'hour':
newDate.setHours(newDate.getHours() + value);
break;
case 'minute':
newDate.setMinutes(newDate.getMinutes() + value);
break;
case 'second':
newDate.setSeconds(newDate.getSeconds() + value);
break;
case 'millisecond':
newDate.setMilliseconds(newDate.getMilliseconds() + value);
break;
}
return newDate;
};
// Retrieve attribute values and calculate the new date and time
const hourAttr = document.querySelector('[ms-code-time-hour]');
const minuteAttr = document.querySelector('[ms-code-time-minute]');
const secondAttr = document.querySelector('[ms-code-time-second]');
const millisecondAttr = document.querySelector('[ms-code-time-millisecond]');
const countdownDateTime = localStorage.getItem('countdownDateTime');
let newDate;
if (countdownDateTime) {
newDate = new Date(countdownDateTime);
} else {
newDate = currentDate;
if (hourAttr.hasAttribute('ms-code-time-hour')) {
const hours = parseInt(hourAttr.getAttribute('ms-code-time-hour'));
newDate = addTime(newDate, 'hour', isNaN(hours) ? 0 : hours);
}
if (minuteAttr.hasAttribute('ms-code-time-minute')) {
const minutes = parseInt(minuteAttr.getAttribute('ms-code-time-minute'));
newDate = addTime(newDate, 'minute', isNaN(minutes) ? 0 : minutes);
}
if (secondAttr.hasAttribute('ms-code-time-second')) {
const seconds = parseInt(secondAttr.getAttribute('ms-code-time-second'));
newDate = addTime(newDate, 'second', isNaN(seconds) ? 0 : seconds);
}
if (millisecondAttr.hasAttribute('ms-code-time-millisecond')) {
const milliseconds = parseInt(millisecondAttr.getAttribute('ms-code-time-millisecond'));
newDate = addTime(newDate, 'millisecond', isNaN(milliseconds) ? 0 : milliseconds);
}
localStorage.setItem('countdownDateTime', newDate);
}
// Step 4: Update the text of the elements to show the continuous countdown
const countdownElements = [hourAttr, minuteAttr, secondAttr, millisecondAttr];
const updateCountdown = () => {
const currentTime = new Date();
const timeDifference = newDate - currentTime;
if (timeDifference > 0) {
const timeParts = [
Math.floor(timeDifference / (1000 * 60 * 60)) % 24, // Hours
Math.floor(timeDifference / (1000 * 60)) % 60, // Minutes
Math.floor(timeDifference / 1000) % 60, // Seconds
Math.floor(timeDifference) % 1000, // Milliseconds
];
// Update the text of the elements with the countdown values
countdownElements.forEach((element, index) => {
const timeValue = timeParts[index];
if (index === 3) {
element.innerText = timeValue.toString().padStart(2, '0').slice(0, 2); // Display only two digits for milliseconds
} else {
element.innerText = timeValue < 10 ? `0${timeValue}` : timeValue;
}
});
// Update the countdown every 10 milliseconds
setTimeout(updateCountdown, 10);
} else {
// Countdown has reached zero or has passed
countdownElements.forEach((element) => {
element.innerText = '00';
});
// Remove elements with ms-code-countdown="hide-on-end" attribute
const hideOnEndElements = document.querySelectorAll('[ms-code-countdown="hide-on-end"]');
hideOnEndElements.forEach((element) => {
element.remove();
});
// Optionally, you can perform additional actions or display a message when the countdown ends
}
};
// Start the countdown
updateCountdown();
</script>
<!-- 💙 MEMBERSCRIPT #9 v0.1 💙 COUNTDOWN BY USER -->
<script>
// Step 1: Get the current date and time
const currentDate = new Date();
// Step 2: Calculate the new date and time based on the attribute values
const addTime = (date, unit, value) => {
const newDate = new Date(date);
switch (unit) {
case 'hour':
newDate.setHours(newDate.getHours() + value);
break;
case 'minute':
newDate.setMinutes(newDate.getMinutes() + value);
break;
case 'second':
newDate.setSeconds(newDate.getSeconds() + value);
break;
case 'millisecond':
newDate.setMilliseconds(newDate.getMilliseconds() + value);
break;
}
return newDate;
};
// Retrieve attribute values and calculate the new date and time
const hourAttr = document.querySelector('[ms-code-time-hour]');
const minuteAttr = document.querySelector('[ms-code-time-minute]');
const secondAttr = document.querySelector('[ms-code-time-second]');
const millisecondAttr = document.querySelector('[ms-code-time-millisecond]');
const countdownDateTime = localStorage.getItem('countdownDateTime');
let newDate;
if (countdownDateTime) {
newDate = new Date(countdownDateTime);
} else {
newDate = currentDate;
if (hourAttr.hasAttribute('ms-code-time-hour')) {
const hours = parseInt(hourAttr.getAttribute('ms-code-time-hour'));
newDate = addTime(newDate, 'hour', isNaN(hours) ? 0 : hours);
}
if (minuteAttr.hasAttribute('ms-code-time-minute')) {
const minutes = parseInt(minuteAttr.getAttribute('ms-code-time-minute'));
newDate = addTime(newDate, 'minute', isNaN(minutes) ? 0 : minutes);
}
if (secondAttr.hasAttribute('ms-code-time-second')) {
const seconds = parseInt(secondAttr.getAttribute('ms-code-time-second'));
newDate = addTime(newDate, 'second', isNaN(seconds) ? 0 : seconds);
}
if (millisecondAttr.hasAttribute('ms-code-time-millisecond')) {
const milliseconds = parseInt(millisecondAttr.getAttribute('ms-code-time-millisecond'));
newDate = addTime(newDate, 'millisecond', isNaN(milliseconds) ? 0 : milliseconds);
}
localStorage.setItem('countdownDateTime', newDate);
}
// Step 4: Update the text of the elements to show the continuous countdown
const countdownElements = [hourAttr, minuteAttr, secondAttr, millisecondAttr];
const updateCountdown = () => {
const currentTime = new Date();
const timeDifference = newDate - currentTime;
if (timeDifference > 0) {
const timeParts = [
Math.floor(timeDifference / (1000 * 60 * 60)) % 24, // Hours
Math.floor(timeDifference / (1000 * 60)) % 60, // Minutes
Math.floor(timeDifference / 1000) % 60, // Seconds
Math.floor(timeDifference) % 1000, // Milliseconds
];
// Update the text of the elements with the countdown values
countdownElements.forEach((element, index) => {
const timeValue = timeParts[index];
if (index === 3) {
element.innerText = timeValue.toString().padStart(2, '0').slice(0, 2); // Display only two digits for milliseconds
} else {
element.innerText = timeValue < 10 ? `0${timeValue}` : timeValue;
}
});
// Update the countdown every 10 milliseconds
setTimeout(updateCountdown, 10);
} else {
// Countdown has reached zero or has passed
countdownElements.forEach((element) => {
element.innerText = '00';
});
// Remove elements with ms-code-countdown="hide-on-end" attribute
const hideOnEndElements = document.querySelectorAll('[ms-code-countdown="hide-on-end"]');
hideOnEndElements.forEach((element) => {
element.remove();
});
// Optionally, you can perform additional actions or display a message when the countdown ends
}
};
// Start the countdown
updateCountdown();
</script>

#8 - Copier dans le presse-papiers
Permettre aux visiteurs de copier des éléments tels que des codes de réduction dans leur presse-papiers en un seul clic.
<!-- 💙 MEMBERSCRIPT #8 v0.1 💙 SIMPLE COPY ELEMENT TO CLIPBOARD -->
<script>
// Step 1: Click the element with the attribute ms-code-copy="trigger"
const triggerElement = document.querySelector('[ms-code-copy="trigger"]');
triggerElement.addEventListener('click', () => {
// Step 2: Copy text from the element with the attribute ms-code-copy="subject" to the clipboard
const subjectElement = document.querySelector('[ms-code-copy="subject"]');
const subjectText = subjectElement.innerText;
// Create a temporary textarea element to facilitate the copying process
const tempTextArea = document.createElement('textarea');
tempTextArea.value = subjectText;
document.body.appendChild(tempTextArea);
// Select the text within the textarea and copy it to the clipboard
tempTextArea.select();
document.execCommand('copy');
// Remove the temporary textarea
document.body.removeChild(tempTextArea);
});
</script>
<!-- 💙 MEMBERSCRIPT #8 v0.1 💙 SIMPLE COPY ELEMENT TO CLIPBOARD -->
<script>
// Step 1: Click the element with the attribute ms-code-copy="trigger"
const triggerElement = document.querySelector('[ms-code-copy="trigger"]');
triggerElement.addEventListener('click', () => {
// Step 2: Copy text from the element with the attribute ms-code-copy="subject" to the clipboard
const subjectElement = document.querySelector('[ms-code-copy="subject"]');
const subjectText = subjectElement.innerText;
// Create a temporary textarea element to facilitate the copying process
const tempTextArea = document.createElement('textarea');
tempTextArea.value = subjectText;
document.body.appendChild(tempTextArea);
// Select the text within the textarea and copy it to the clipboard
tempTextArea.select();
document.execCommand('copy');
// Remove the temporary textarea
document.body.removeChild(tempTextArea);
});
</script>

#7 - Éléments de chargement à retardement
Retarder l'apparition des éléments pendant une durée déterminée afin de donner à la page le temps de se mettre à jour avec les données correctes concernant les membres.
<!-- 💙 MEMBERSCRIPT #7 v0.1 💙 DELAY LOADING ELEMENTS -->
<script>
document.addEventListener("DOMContentLoaded", function() {
const elementsToDelay = document.querySelectorAll('[ms-code-delay]');
elementsToDelay.forEach(element => {
element.style.visibility = "hidden"; // Hide the element initially
});
setTimeout(function() {
elementsToDelay.forEach(element => {
element.style.visibility = "visible"; // Make the element visible after the delay
element.style.opacity = "0"; // Set the initial opacity to 0
element.style.animation = "fadeIn 0.5s"; // Apply the fadeIn animation
element.addEventListener("animationend", function() {
element.style.opacity = "1"; // Set opacity to 1 at the end of the animation
});
});
}, 1000);
});
</script>
<style>
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
</style>
<!-- 💙 MEMBERSCRIPT #7 v0.1 💙 DELAY LOADING ELEMENTS -->
<script>
document.addEventListener("DOMContentLoaded", function() {
const elementsToDelay = document.querySelectorAll('[ms-code-delay]');
elementsToDelay.forEach(element => {
element.style.visibility = "hidden"; // Hide the element initially
});
setTimeout(function() {
elementsToDelay.forEach(element => {
element.style.visibility = "visible"; // Make the element visible after the delay
element.style.opacity = "0"; // Set the initial opacity to 0
element.style.animation = "fadeIn 0.5s"; // Apply the fadeIn animation
element.addEventListener("animationend", function() {
element.style.opacity = "1"; // Set opacity to 1 at the end of the animation
});
});
}, 1000);
});
</script>
<style>
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
</style>

#6 - Créer des groupes d'éléments à partir du JSON des membres
Afficher des groupes JSON aux membres connectés en utilisant un élément placeholder construit dans le Webflow.
<!-- 💙 MEMBERSCRIPT #6 v0.1 💙 CREATE ITEM GROUPS FROM JSON -->
<script>
document.addEventListener("DOMContentLoaded", async function() {
const memberstack = window.$memberstackDom;
// Function to display nested/sub items
const displayNestedItems = async function(printList) {
const jsonGroup = printList.getAttribute('ms-code-print-list');
const placeholder = printList.querySelector(`[ms-code-print-item="${jsonGroup}"]`);
if (!placeholder) return;
const itemTemplate = placeholder.outerHTML;
const itemContainer = document.createElement('div'); // Create a new container for the items
const member = await memberstack.getMemberJSON();
const items = member.data && member.data[jsonGroup] ? Object.values(member.data[jsonGroup]) : [];
if (items.length === 0) return; // If no items, exit the function
items.forEach(item => {
if (Object.keys(item).length === 0) return;
const newItem = document.createElement('div');
newItem.innerHTML = itemTemplate;
const itemElements = newItem.querySelectorAll('[ms-code-item-text]');
itemElements.forEach(itemElement => {
const jsonKey = itemElement.getAttribute('ms-code-item-text');
const value = item && item[jsonKey] ? item[jsonKey] : '';
itemElement.textContent = value;
});
// Add item key attribute
const itemKey = Object.keys(member.data[jsonGroup]).find(k => member.data[jsonGroup][k] === item);
newItem.firstChild.setAttribute('ms-code-item-key', itemKey);
itemContainer.appendChild(newItem.firstChild);
});
// Replace the existing list with the new items
printList.innerHTML = itemContainer.innerHTML;
};
// Call displayNestedItems function on initial page load for each instance
const printLists = document.querySelectorAll('[ms-code-print-list]');
printLists.forEach(printList => {
displayNestedItems(printList);
});
// Add click event listener to elements with ms-code-update="json"
const updateButtons = document.querySelectorAll('[ms-code-update="json"]');
updateButtons.forEach(button => {
button.addEventListener("click", async function() {
// Add a delay of 500ms
await new Promise(resolve => setTimeout(resolve, 500));
printLists.forEach(printList => {
displayNestedItems(printList);
});
});
});
});
</script>
<!-- 💙 MEMBERSCRIPT #6 v0.1 💙 CREATE ITEM GROUPS FROM JSON -->
<script>
document.addEventListener("DOMContentLoaded", async function() {
const memberstack = window.$memberstackDom;
// Function to display nested/sub items
const displayNestedItems = async function(printList) {
const jsonGroup = printList.getAttribute('ms-code-print-list');
const placeholder = printList.querySelector(`[ms-code-print-item="${jsonGroup}"]`);
if (!placeholder) return;
const itemTemplate = placeholder.outerHTML;
const itemContainer = document.createElement('div'); // Create a new container for the items
const member = await memberstack.getMemberJSON();
const items = member.data && member.data[jsonGroup] ? Object.values(member.data[jsonGroup]) : [];
if (items.length === 0) return; // If no items, exit the function
items.forEach(item => {
if (Object.keys(item).length === 0) return;
const newItem = document.createElement('div');
newItem.innerHTML = itemTemplate;
const itemElements = newItem.querySelectorAll('[ms-code-item-text]');
itemElements.forEach(itemElement => {
const jsonKey = itemElement.getAttribute('ms-code-item-text');
const value = item && item[jsonKey] ? item[jsonKey] : '';
itemElement.textContent = value;
});
// Add item key attribute
const itemKey = Object.keys(member.data[jsonGroup]).find(k => member.data[jsonGroup][k] === item);
newItem.firstChild.setAttribute('ms-code-item-key', itemKey);
itemContainer.appendChild(newItem.firstChild);
});
// Replace the existing list with the new items
printList.innerHTML = itemContainer.innerHTML;
};
// Call displayNestedItems function on initial page load for each instance
const printLists = document.querySelectorAll('[ms-code-print-list]');
printLists.forEach(printList => {
displayNestedItems(printList);
});
// Add click event listener to elements with ms-code-update="json"
const updateButtons = document.querySelectorAll('[ms-code-update="json"]');
updateButtons.forEach(button => {
button.addEventListener("click", async function() {
// Add a delay of 500ms
await new Promise(resolve => setTimeout(resolve, 500));
printLists.forEach(printList => {
displayNestedItems(printList);
});
});
});
});
</script>

#5 - Remplir du texte à partir d'un simple élément JSON
Utilisez Member JSON pour mettre à jour le texte de n'importe quel élément de votre page.
<!-- 💙 MEMBERSCRIPT #5 v0.1 💙 FILL TEXT BASED ON SIMPLE ITEM IN JSON -->
<script>
document.addEventListener("DOMContentLoaded", function() {
const memberstack = window.$memberstackDom;
// Function to fill text elements with attribute ms-code-fill-text
const fillTextElements = async function() {
// Retrieve the current member JSON data
const member = await memberstack.getMemberJSON();
// Fill text elements with attribute ms-code-fill-text
const textElements = document.querySelectorAll('[ms-code-fill-text]');
textElements.forEach(element => {
const jsonKey = element.getAttribute('ms-code-fill-text');
const value = member.data && member.data[jsonKey] ? member.data[jsonKey] : '';
element.textContent = value;
});
};
// Function to handle script #4 event
const handleScript4Event = async function() {
// Add a delay of 500ms
await new Promise(resolve => setTimeout(resolve, 500));
await fillTextElements();
};
// Add click event listener to elements with ms-code-update="json"
const updateButtons = document.querySelectorAll('[ms-code-update="json"]');
updateButtons.forEach(button => {
button.addEventListener("click", handleScript4Event);
});
// Call fillTextElements function on initial page load
fillTextElements();
});
</script>
<!-- 💙 MEMBERSCRIPT #5 v0.1 💙 FILL TEXT BASED ON SIMPLE ITEM IN JSON -->
<script>
document.addEventListener("DOMContentLoaded", function() {
const memberstack = window.$memberstackDom;
// Function to fill text elements with attribute ms-code-fill-text
const fillTextElements = async function() {
// Retrieve the current member JSON data
const member = await memberstack.getMemberJSON();
// Fill text elements with attribute ms-code-fill-text
const textElements = document.querySelectorAll('[ms-code-fill-text]');
textElements.forEach(element => {
const jsonKey = element.getAttribute('ms-code-fill-text');
const value = member.data && member.data[jsonKey] ? member.data[jsonKey] : '';
element.textContent = value;
});
};
// Function to handle script #4 event
const handleScript4Event = async function() {
// Add a delay of 500ms
await new Promise(resolve => setTimeout(resolve, 500));
await fillTextElements();
};
// Add click event listener to elements with ms-code-update="json"
const updateButtons = document.querySelectorAll('[ms-code-update="json"]');
updateButtons.forEach(button => {
button.addEventListener("click", handleScript4Event);
});
// Call fillTextElements function on initial page load
fillTextElements();
});
</script>

#4 - Mettre à jour le JSON des membres dans le stockage local au moment du clic
Ajoutez cet attribut à tout bouton/élément qui doit déclencher une mise à jour JSON après un court délai.
<!-- 💙 MEMBERSCRIPT #4 v0.1 💙 UPDATE MEMBER JSON IN LOCAL STORAGE ON BUTTON CLICK -->
<script>
document.addEventListener("DOMContentLoaded", function() {
const updateButtons = document.querySelectorAll('[ms-code-update="json"]');
updateButtons.forEach(button => {
button.addEventListener("click", async function() {
const memberstack = window.$memberstackDom;
// Add a delay
await new Promise(resolve => setTimeout(resolve, 500));
// Retrieve the current member JSON data
const member = await memberstack.getMemberJSON();
// Save the member JSON as a local storage item
localStorage.setItem("memberJSON", JSON.stringify(member));
});
});
});
</script>
<!-- 💙 MEMBERSCRIPT #4 v0.1 💙 UPDATE MEMBER JSON IN LOCAL STORAGE ON BUTTON CLICK -->
<script>
document.addEventListener("DOMContentLoaded", function() {
const updateButtons = document.querySelectorAll('[ms-code-update="json"]');
updateButtons.forEach(button => {
button.addEventListener("click", async function() {
const memberstack = window.$memberstackDom;
// Add a delay
await new Promise(resolve => setTimeout(resolve, 500));
// Retrieve the current member JSON data
const member = await memberstack.getMemberJSON();
// Save the member JSON as a local storage item
localStorage.setItem("memberJSON", JSON.stringify(member));
});
});
});
</script>

#3 - Enregistrer le JSON des membres dans le stockage local lors du chargement de la page
Créer un objet localstorage contenant le JSON du membre connecté au chargement de la page
<!-- 💙 MEMBERSCRIPT #3 v0.1 💙 SAVE JSON TO LOCALSTORAGE ON PAGE LOAD -->
<script>
document.addEventListener("DOMContentLoaded", async function() {
const memberstack = window.$memberstackDom;
// Retrieve the current member JSON data
const member = await memberstack.getMemberJSON();
// Save the member JSON as a local storage item
localStorage.setItem("memberJSON", JSON.stringify(member));
});
</script>
<!-- 💙 MEMBERSCRIPT #3 v0.1 💙 SAVE JSON TO LOCALSTORAGE ON PAGE LOAD -->
<script>
document.addEventListener("DOMContentLoaded", async function() {
const memberstack = window.$memberstackDom;
// Retrieve the current member JSON data
const member = await memberstack.getMemberJSON();
// Save the member JSON as a local storage item
localStorage.setItem("memberJSON", JSON.stringify(member));
});
</script>

#2 - Ajouter des groupes d'éléments au JSON des membres
Permet aux membres d'ajouter des éléments/groupes imbriqués à leur JSON de membre.
<!-- 💙 MEMBERSCRIPT #2 v0.1 💙 ADD ITEM GROUPS TO MEMBER JSON -->
<script>
document.addEventListener("DOMContentLoaded", function() {
const msCodeForm2 = document.querySelector('[ms-code="form2"]');
const jsonList = msCodeForm2.getAttribute("ms-code-json-list");
msCodeForm2.addEventListener('submit', async function(event) {
event.preventDefault(); // Prevent the default form submission
// Retrieve the current member JSON data
const memberstack = window.$memberstackDom;
const member = await memberstack.getMemberJSON();
// Create a new member.data object if it doesn't already exist
if (!member.data) {
member.data = {};
}
// Check if the friends group already exists
if (!member.data[jsonList]) {
// Create a new friends group object
member.data[jsonList] = {};
}
// Retrieve the input values for creating the subgroup
const inputs = msCodeForm2.querySelectorAll('[ms-code-json-name]');
const subgroup = {};
inputs.forEach(input => {
const jsonName = input.getAttribute('ms-code-json-name');
const newItem = input.value;
subgroup[jsonName] = newItem;
});
// Generate a unique key for the new subgroup prefixed with the main group name
const timestamp = Date.now();
const subgroupKey = `${jsonList}-${timestamp}`;
// Create the new subgroup within the friends group
member.data[jsonList][subgroupKey] = subgroup;
// Update the member JSON with the new data
await memberstack.updateMemberJSON({
json: member.data
});
// Log a message to the console
console.log(`New subgroup with key ${subgroupKey} has been created within ${jsonList} group.`);
// Reset the input values
inputs.forEach(input => {
input.value = "";
});
});
});
</script>
<!-- 💙 MEMBERSCRIPT #2 v0.1 💙 ADD ITEM GROUPS TO MEMBER JSON -->
<script>
document.addEventListener("DOMContentLoaded", function() {
const msCodeForm2 = document.querySelector('[ms-code="form2"]');
const jsonList = msCodeForm2.getAttribute("ms-code-json-list");
msCodeForm2.addEventListener('submit', async function(event) {
event.preventDefault(); // Prevent the default form submission
// Retrieve the current member JSON data
const memberstack = window.$memberstackDom;
const member = await memberstack.getMemberJSON();
// Create a new member.data object if it doesn't already exist
if (!member.data) {
member.data = {};
}
// Check if the friends group already exists
if (!member.data[jsonList]) {
// Create a new friends group object
member.data[jsonList] = {};
}
// Retrieve the input values for creating the subgroup
const inputs = msCodeForm2.querySelectorAll('[ms-code-json-name]');
const subgroup = {};
inputs.forEach(input => {
const jsonName = input.getAttribute('ms-code-json-name');
const newItem = input.value;
subgroup[jsonName] = newItem;
});
// Generate a unique key for the new subgroup prefixed with the main group name
const timestamp = Date.now();
const subgroupKey = `${jsonList}-${timestamp}`;
// Create the new subgroup within the friends group
member.data[jsonList][subgroupKey] = subgroup;
// Update the member JSON with the new data
await memberstack.updateMemberJSON({
json: member.data
});
// Log a message to the console
console.log(`New subgroup with key ${subgroupKey} has been created within ${jsonList} group.`);
// Reset the input values
inputs.forEach(input => {
input.value = "";
});
});
});
</script>

#1 - Ajouter des éléments au JSON des membres
Permettre aux membres d'enregistrer des éléments simples dans leur JSON sans écrire de code.
<!-- 💙 MEMBERSCRIPT #1 v0.1 💙 ADD INDIVIDUAL ITEMS TO MEMBER JSON -->
<script>
document.addEventListener("DOMContentLoaded", function() {
const forms = document.querySelectorAll('[ms-code="form1"]');
forms.forEach(form => {
const jsonType = form.getAttribute("ms-code-json-type");
const jsonList = form.getAttribute("ms-code-json-list");
form.addEventListener('submit', async function(event) {
event.preventDefault(); // Prevent the default form submission
// Retrieve the current member JSON data
const memberstack = window.$memberstackDom;
const member = await memberstack.getMemberJSON();
// Create a new member.data object if it doesn't already exist
if (!member.data) {
member.data = {};
}
if (jsonType === "group") {
// Check if the group already exists
if (!member.data[jsonList]) {
// Create a new group object
member.data[jsonList] = {};
}
// Iterate over the inputs with ms-code-json-name attribute
const inputs = form.querySelectorAll('[ms-code-json-name]');
inputs.forEach(input => {
const jsonName = input.getAttribute('ms-code-json-name');
const newItem = input.value;
member.data[jsonList][jsonName] = newItem;
});
// Log a message to the console for group type
console.log(`Item(s) have been added to member JSON with group key ${jsonList}.`);
} else if (jsonType === "array") {
// Check if the array already exists
if (!member.data[jsonList]) {
// Create a new array
member.data[jsonList] = [];
}
// Retrieve the input values for the array type
const inputs = form.querySelectorAll('[ms-code-json-name]');
inputs.forEach(input => {
const jsonName = input.getAttribute('ms-code-json-name');
const newItem = input.value;
member.data[jsonList].push(newItem);
});
// Log a message to the console for array type
console.log(`Item(s) have been added to member JSON with array key ${jsonList}.`);
} else {
// Retrieve the input value and key for the basic item type
const input = form.querySelector('[ms-code-json-name]');
const jsonName = input.getAttribute('ms-code-json-name');
const newItem = input.value;
member.data[jsonName] = newItem;
// Log a message to the console for basic item type
console.log(`Item ${newItem} has been added to member JSON with key ${jsonName}.`);
}
// Update the member JSON with the new data
await memberstack.updateMemberJSON({
json: member.data
});
// Reset the input values
const inputs = form.querySelectorAll('[ms-code-json-name]');
inputs.forEach(input => {
input.value = "";
});
});
});
});
</script>
<!-- 💙 MEMBERSCRIPT #1 v0.1 💙 ADD INDIVIDUAL ITEMS TO MEMBER JSON -->
<script>
document.addEventListener("DOMContentLoaded", function() {
const forms = document.querySelectorAll('[ms-code="form1"]');
forms.forEach(form => {
const jsonType = form.getAttribute("ms-code-json-type");
const jsonList = form.getAttribute("ms-code-json-list");
form.addEventListener('submit', async function(event) {
event.preventDefault(); // Prevent the default form submission
// Retrieve the current member JSON data
const memberstack = window.$memberstackDom;
const member = await memberstack.getMemberJSON();
// Create a new member.data object if it doesn't already exist
if (!member.data) {
member.data = {};
}
if (jsonType === "group") {
// Check if the group already exists
if (!member.data[jsonList]) {
// Create a new group object
member.data[jsonList] = {};
}
// Iterate over the inputs with ms-code-json-name attribute
const inputs = form.querySelectorAll('[ms-code-json-name]');
inputs.forEach(input => {
const jsonName = input.getAttribute('ms-code-json-name');
const newItem = input.value;
member.data[jsonList][jsonName] = newItem;
});
// Log a message to the console for group type
console.log(`Item(s) have been added to member JSON with group key ${jsonList}.`);
} else if (jsonType === "array") {
// Check if the array already exists
if (!member.data[jsonList]) {
// Create a new array
member.data[jsonList] = [];
}
// Retrieve the input values for the array type
const inputs = form.querySelectorAll('[ms-code-json-name]');
inputs.forEach(input => {
const jsonName = input.getAttribute('ms-code-json-name');
const newItem = input.value;
member.data[jsonList].push(newItem);
});
// Log a message to the console for array type
console.log(`Item(s) have been added to member JSON with array key ${jsonList}.`);
} else {
// Retrieve the input value and key for the basic item type
const input = form.querySelector('[ms-code-json-name]');
const jsonName = input.getAttribute('ms-code-json-name');
const newItem = input.value;
member.data[jsonName] = newItem;
// Log a message to the console for basic item type
console.log(`Item ${newItem} has been added to member JSON with key ${jsonName}.`);
}
// Update the member JSON with the new data
await memberstack.updateMemberJSON({
json: member.data
});
// Reset the input values
const inputs = form.querySelectorAll('[ms-code-json-name]');
inputs.forEach(input => {
input.value = "";
});
});
});
});
</script>
Besoin d'aide avec MemberScripts ? Rejoignez notre communauté Slack de plus de 5 500 membres ! 🙌
Les MemberScripts sont une ressource communautaire de Memberstack - si vous avez besoin d'aide pour les faire fonctionner avec votre projet, rejoignez le Slack de Memberstack 2.0 et demandez de l'aide !
Rejoignez notre SlackDécouvrez les entreprises qui ont réussi avec Memberstack
Ne vous contentez pas de nous croire sur parole, consultez les entreprises de toutes tailles qui font confiance à Memberstack pour leur authentification et leurs paiements.
Commencez à construire vos rêves
Memberstack est 100% gratuit jusqu'à ce que vous soyez prêt à vous lancer - alors, qu'attendez-vous ? Créez votre première application et commencez à construire dès aujourd'hui.