Komponenten
Schablonen
Attribute
Integrationen
Standort-Tester
Benutzerdefinierter Code

Mitglieder-Skripte

Eine attributbasierte Lösung zum Hinzufügen von Funktionen zu Ihrer Webflow-Site.
Kopieren Sie einfach etwas Code, fügen Sie einige Attribute hinzu, und schon sind Sie fertig.

Vielen Dank! Ihr Beitrag ist eingegangen!
Huch! Beim Absenden des Formulars ist etwas schief gelaufen.
Benötigen Sie Hilfe mit MemberScripts?

Alle Memberstack-Kunden können im 2.0 Slack um Unterstützung bitten. Bitte beachten Sie, dass dies keine offiziellen Funktionen sind und der Support nicht garantiert werden kann.

UX
Erreichbarkeit

#149 - Favicon for Dark/Light Mode

Use this script to update your website's favicon based on the user's system color scheme preference.


<!-- 💙 MEMBERSCRIPT #149 v0.1 💙 - FAVICON FOR DARK/LIGHT MODE -->
<script>
  // Helper: Retrieve or create a favicon element
  function getFaviconElement() {
    let favicon = document.querySelector('link[rel="icon"]') ||
        document.querySelector('link[rel="shortcut icon"]');
    if (!favicon) {
      favicon = document.createElement('link');
      favicon.rel = 'icon';
      document.head.appendChild(favicon);
    }
    return favicon;
  }

  // Function to update the favicon based on dark mode
  function updateFavicon(e) {
    const darkModeOn = e ? e.matches : window.matchMedia('(prefers-color-scheme: dark)').matches;
    const favicon = getFaviconElement();
    // Update these paths to your favicon assets in Webflow’s Asset Manager or a CDN
    favicon.href = darkModeOn
      ? 'https://cdn.prod.website-files.com/67fcff014042c2f5945437c0/67fd000f85b2a9f281a373ca_Dark%20Mode%20Logo.png'
      : 'https://cdn.prod.website-files.com/67fcff014042c2f5945437c0/67fd000f1c2fa3cebee1b150_Light%20Mode%20Logo.png';
  }

  // Initialize the favicon update on page load
  updateFavicon();

  // Listen for changes in the dark mode media query
  const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
  if (typeof darkModeMediaQuery.addEventListener === 'function') {
    darkModeMediaQuery.addEventListener('change', updateFavicon);
  } else if (typeof darkModeMediaQuery.addListener === 'function') {
    darkModeMediaQuery.addListener(updateFavicon);
  }
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #149 v0.1 💙 - FAVICON FOR DARK/LIGHT MODE -->
<script>
  // Helper: Retrieve or create a favicon element
  function getFaviconElement() {
    let favicon = document.querySelector('link[rel="icon"]') ||
        document.querySelector('link[rel="shortcut icon"]');
    if (!favicon) {
      favicon = document.createElement('link');
      favicon.rel = 'icon';
      document.head.appendChild(favicon);
    }
    return favicon;
  }

  // Function to update the favicon based on dark mode
  function updateFavicon(e) {
    const darkModeOn = e ? e.matches : window.matchMedia('(prefers-color-scheme: dark)').matches;
    const favicon = getFaviconElement();
    // Update these paths to your favicon assets in Webflow’s Asset Manager or a CDN
    favicon.href = darkModeOn
      ? 'https://cdn.prod.website-files.com/67fcff014042c2f5945437c0/67fd000f85b2a9f281a373ca_Dark%20Mode%20Logo.png'
      : 'https://cdn.prod.website-files.com/67fcff014042c2f5945437c0/67fd000f1c2fa3cebee1b150_Light%20Mode%20Logo.png';
  }

  // Initialize the favicon update on page load
  updateFavicon();

  // Listen for changes in the dark mode media query
  const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
  if (typeof darkModeMediaQuery.addEventListener === 'function') {
    darkModeMediaQuery.addEventListener('change', updateFavicon);
  } else if (typeof darkModeMediaQuery.addListener === 'function') {
    darkModeMediaQuery.addListener(updateFavicon);
  }
</script>
Ansicht Memberscript
UX
Erreichbarkeit

#148 - Disable Webflow Form Success Window

Use this script to override Webflow's default form submission behavior by hiding the success message.


<!-- 💙 MEMBERSCRIPT #148 v0.1 💙 - DISABLE WEBFLOW FORM SUCCESS WINDOW -->
<script>
  document.addEventListener('DOMContentLoaded', function () {
    const form = document.querySelector('[ms-code-form="form"]');
    const successEl = document.querySelector('[ms-code-success="true"]');

    if (!form || !successEl) return;

    const observer = new MutationObserver(() => {
      const isVisible = window.getComputedStyle(successEl).display !== 'none';
      if (isVisible) {
        successEl.style.display = 'none';
        form.style.display = 'block';
      }
    });

    observer.observe(successEl, { attributes: true, attributeFilter: ['style'] });

    // Cleanup observer when done (optional, for performance)
    form.addEventListener('w-form-success', () => {
      setTimeout(() => {
        observer.disconnect();
      }, 100);
    });
  });
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #148 v0.1 💙 - DISABLE WEBFLOW FORM SUCCESS WINDOW -->
<script>
  document.addEventListener('DOMContentLoaded', function () {
    const form = document.querySelector('[ms-code-form="form"]');
    const successEl = document.querySelector('[ms-code-success="true"]');

    if (!form || !successEl) return;

    const observer = new MutationObserver(() => {
      const isVisible = window.getComputedStyle(successEl).display !== 'none';
      if (isVisible) {
        successEl.style.display = 'none';
        form.style.display = 'block';
      }
    });

    observer.observe(successEl, { attributes: true, attributeFilter: ['style'] });

    // Cleanup observer when done (optional, for performance)
    form.addEventListener('w-form-success', () => {
      setTimeout(() => {
        observer.disconnect();
      }, 100);
    });
  });
</script>
Ansicht Memberscript
UX
Erreichbarkeit
Modale
Sicherheit

#147 - Age Verification Popup with Cookies in Webflow

Use this script to add an age verification popup to your Webflow site.


<!-- 💙 MEMBERSCRIPT #147 v0.1 💙 - AGE VERIFICATION POPUP WITH COOKIES -->
<script>
  // Simple cookie helper functions
  function setCookie(name, value, days) {
    const date = new Date();
    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
    document.cookie = name + "=" + value + "; expires=" + date.toUTCString() + "; path=/";
  }

  function getCookie(name) {
    const cname = name + "=";
    const decodedCookie = decodeURIComponent(document.cookie);
    const cookies = decodedCookie.split(';');
    for (let i = 0; i < cookies.length; i++) {
      let c = cookies[i].trim();
      if (c.indexOf(cname) === 0) {
        return c.substring(cname.length, c.length);
      }
    }
    return "";
  }

  document.addEventListener('DOMContentLoaded', function() {
    // Select the age gate element via ms-code attribute
    const ageGateEl = document.querySelector('[ms-code-agegate]');

    // On page load: if the cookie exists, hide the age gate
    if (getCookie('ms-code-ageVerified') === 'true') {  
      if (ageGateEl) ageGateEl.style.display = 'none';
    }

    // Listen for clicks on elements with ms-code-click
    document.addEventListener('click', function(event) {
      if (event.target.closest('[ms-code-click="confirmAge"]')) {
        setCookie('ms-code-ageVerified', 'true', 30);
        if (ageGateEl) ageGateEl.style.display = 'none';
      } else if (event.target.closest('[ms-code-click="denyAge"]')) {
        window.location.href = 'https://age-verification-popup-with-cookies.webflow.io/access-denied'; // Change URL as needed
      }
    });
  });
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #147 v0.1 💙 - AGE VERIFICATION POPUP WITH COOKIES -->
<script>
  // Simple cookie helper functions
  function setCookie(name, value, days) {
    const date = new Date();
    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
    document.cookie = name + "=" + value + "; expires=" + date.toUTCString() + "; path=/";
  }

  function getCookie(name) {
    const cname = name + "=";
    const decodedCookie = decodeURIComponent(document.cookie);
    const cookies = decodedCookie.split(';');
    for (let i = 0; i < cookies.length; i++) {
      let c = cookies[i].trim();
      if (c.indexOf(cname) === 0) {
        return c.substring(cname.length, c.length);
      }
    }
    return "";
  }

  document.addEventListener('DOMContentLoaded', function() {
    // Select the age gate element via ms-code attribute
    const ageGateEl = document.querySelector('[ms-code-agegate]');

    // On page load: if the cookie exists, hide the age gate
    if (getCookie('ms-code-ageVerified') === 'true') {  
      if (ageGateEl) ageGateEl.style.display = 'none';
    }

    // Listen for clicks on elements with ms-code-click
    document.addEventListener('click', function(event) {
      if (event.target.closest('[ms-code-click="confirmAge"]')) {
        setCookie('ms-code-ageVerified', 'true', 30);
        if (ageGateEl) ageGateEl.style.display = 'none';
      } else if (event.target.closest('[ms-code-click="denyAge"]')) {
        window.location.href = 'https://age-verification-popup-with-cookies.webflow.io/access-denied'; // Change URL as needed
      }
    });
  });
</script>
Ansicht Memberscript
UX
Erreichbarkeit
Modale

#146 - Stop Videos from Playing When A Modal Closes

Automatically stop video playback when closing modals in Webflow.


<!-- 💙 MEMBERSCRIPT #146 v0.1 💙 - STOP VIDEOS FROM PLAYING WHEN A MODAL CLOSES -->
<script>
  document.addEventListener('DOMContentLoaded', function() {
    // Select all modals on the page
    var modals = document.querySelectorAll('[data-ms-modal="modal"]');

    function initializeModal(modal) {
      var iframe = modal.querySelector('iframe');
      if (!iframe) return; // If no iframe found, do nothing
      var originalSrc = iframe.dataset.src || iframe.src;

      // Function to stop video playback
      function stopVideo() {
        iframe.src = "";
        setTimeout(() => {
          iframe.src = originalSrc;
        }, 100);
      }

      // Attach event listeners to all close buttons inside the modal
      var closeBtns = modal.querySelectorAll('[data-ms-modal="close"]');
      closeBtns.forEach(function(closeBtn) {
        closeBtn.addEventListener('click', function(e) {
          e.preventDefault();
          stopVideo();
        });
      });

      // Also close the modal when clicking outside the content
      modal.addEventListener('click', function(e) {
        if (e.target === modal) {
          stopVideo();
        }
      });
    }

    // Initialize all modals
    modals.forEach(initializeModal);
  });
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #146 v0.1 💙 - STOP VIDEOS FROM PLAYING WHEN A MODAL CLOSES -->
<script>
  document.addEventListener('DOMContentLoaded', function() {
    // Select all modals on the page
    var modals = document.querySelectorAll('[data-ms-modal="modal"]');

    function initializeModal(modal) {
      var iframe = modal.querySelector('iframe');
      if (!iframe) return; // If no iframe found, do nothing
      var originalSrc = iframe.dataset.src || iframe.src;

      // Function to stop video playback
      function stopVideo() {
        iframe.src = "";
        setTimeout(() => {
          iframe.src = originalSrc;
        }, 100);
      }

      // Attach event listeners to all close buttons inside the modal
      var closeBtns = modal.querySelectorAll('[data-ms-modal="close"]');
      closeBtns.forEach(function(closeBtn) {
        closeBtn.addEventListener('click', function(e) {
          e.preventDefault();
          stopVideo();
        });
      });

      // Also close the modal when clicking outside the content
      modal.addEventListener('click', function(e) {
        if (e.target === modal) {
          stopVideo();
        }
      });
    }

    // Initialize all modals
    modals.forEach(initializeModal);
  });
</script>
Ansicht Memberscript
UX
Erreichbarkeit

#145 - Automatically Save & Prefill Forms

Automatically save and prefill forms in a browsers localStorage upon form submission.


<!-- 💙 MEMBERSCRIPT #145 v0.1 💙 - HOW TO PRE-FILL FORM INPUT FIELDS AT PAGE LOAD -->
<script>
  document.addEventListener('DOMContentLoaded', function() {
    // Function to store form data in localStorage
    function storeFormData() {
      const fields = document.querySelectorAll('input[ms-code-field-id], textarea[ms-code-field-id], select[ms-code-field-id]');
      fields.forEach(function(field) {
        const fieldId = field.getAttribute('ms-code-field-id');
        const value = field.value.trim();
        if (value) {
          localStorage.setItem(fieldId, value);
        }
      });
    }

    // Function to pre-fill form fields with stored data
    function preFillForm() {
      const fields = document.querySelectorAll('input[ms-code-field-id], textarea[ms-code-field-id], select[ms-code-field-id]');
      fields.forEach(function(field) {
        const fieldId = field.getAttribute('ms-code-field-id');
        const storedValue = localStorage.getItem(fieldId);
        if (storedValue) {
          field.value = storedValue;
        }
      });
    }

    // Handle form submission
    const form = document.querySelector('#my-form, form[ms-code-form-id]');
    if (form) {
      form.addEventListener('submit', function(event) {
        event.preventDefault(); // Prevent default form submission
        storeFormData();

        // Refresh the page after storing data
        setTimeout(function() {
          location.reload();
        }, 500); // Short delay to simulate form submission
      });
    }

    // Pre-fill form fields when the page loads
    preFillForm();
  });
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #145 v0.1 💙 - HOW TO PRE-FILL FORM INPUT FIELDS AT PAGE LOAD -->
<script>
  document.addEventListener('DOMContentLoaded', function() {
    // Function to store form data in localStorage
    function storeFormData() {
      const fields = document.querySelectorAll('input[ms-code-field-id], textarea[ms-code-field-id], select[ms-code-field-id]');
      fields.forEach(function(field) {
        const fieldId = field.getAttribute('ms-code-field-id');
        const value = field.value.trim();
        if (value) {
          localStorage.setItem(fieldId, value);
        }
      });
    }

    // Function to pre-fill form fields with stored data
    function preFillForm() {
      const fields = document.querySelectorAll('input[ms-code-field-id], textarea[ms-code-field-id], select[ms-code-field-id]');
      fields.forEach(function(field) {
        const fieldId = field.getAttribute('ms-code-field-id');
        const storedValue = localStorage.getItem(fieldId);
        if (storedValue) {
          field.value = storedValue;
        }
      });
    }

    // Handle form submission
    const form = document.querySelector('#my-form, form[ms-code-form-id]');
    if (form) {
      form.addEventListener('submit', function(event) {
        event.preventDefault(); // Prevent default form submission
        storeFormData();

        // Refresh the page after storing data
        setTimeout(function() {
          location.reload();
        }, 500); // Short delay to simulate form submission
      });
    }

    // Pre-fill form fields when the page loads
    preFillForm();
  });
</script>
Ansicht Memberscript
Marketing
JSON
SEO

#144 - Track Users Login History & Active Users

Automatically track a members login history, keep a login streak and total visits


<!-- 💙 MEMBERSCRIPT #144 v0.1 💙 - TRACK A USERS LOGIN HISTORY & ACTIVE USERS -->
<script>
  (function(){
    const memberstack = window.$memberstackDom;

    // Helper: Execute callback when Memberstack is ready
    function onMemberstackReady(cb) {
      if (window.$memberstackReady) {
        cb();
      } else {
        document.addEventListener("memberstack.ready", cb);
      }
    }

    async function initTracking() {
      // Check if a member is logged in (via localStorage)
      const currentUser = JSON.parse(localStorage.getItem("_ms-mem") || "null");
      if (!currentUser) {
        console.warn("No logged-in member found. Tracking not applied.");
        return;
      }

      // Retrieve member metadata
      const memberJson = await memberstack.getMemberJSON();
      let metadata = memberJson.data || {};

      // Ensure userVisits exists as an array
      metadata.userVisits = Array.isArray(metadata.userVisits) ? metadata.userVisits : [];

      // Use ISO date (YYYY-MM-DD) to record one visit per day
      const today = new Date().toISOString().split("T")[0];
      if (!metadata.userVisits.includes(today)) {
        metadata.userVisits.push(today);
      }

      // Helper: Compute consecutive login streak from userVisits
      function computeStreak(visits) {
        if (!visits.length) return 0;
        // Ensure dates are unique and sorted ascending
        const uniqueVisits = [...new Set(visits)].sort();
        let streak = 1;
        let currentDate = new Date(uniqueVisits[uniqueVisits.length - 1]);
        for (let i = uniqueVisits.length - 2; i >= 0; i--) {
          const prevDate = new Date(uniqueVisits[i]);
          const diffDays = Math.floor((currentDate - prevDate) / (1000 * 60 * 60 * 24));
          if (diffDays === 1) {
            streak++;
            currentDate = prevDate;
          } else {
            break;
          }
        }
        return streak;
      }

      // Calculate the login streak and total visits
      metadata.loginStreak = computeStreak(metadata.userVisits);
      metadata.totalVisits = metadata.userVisits.length;

      // Update Memberstack metadata
      await memberstack.updateMemberJSON({ json: metadata });

      console.log("User visits:", metadata.userVisits);
      console.log("Login streak:", metadata.loginStreak);
      console.log("Total visits:", metadata.totalVisits);
    }

    onMemberstackReady(initTracking);
  })();
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #144 v0.1 💙 - TRACK A USERS LOGIN HISTORY & ACTIVE USERS -->
<script>
  (function(){
    const memberstack = window.$memberstackDom;

    // Helper: Execute callback when Memberstack is ready
    function onMemberstackReady(cb) {
      if (window.$memberstackReady) {
        cb();
      } else {
        document.addEventListener("memberstack.ready", cb);
      }
    }

    async function initTracking() {
      // Check if a member is logged in (via localStorage)
      const currentUser = JSON.parse(localStorage.getItem("_ms-mem") || "null");
      if (!currentUser) {
        console.warn("No logged-in member found. Tracking not applied.");
        return;
      }

      // Retrieve member metadata
      const memberJson = await memberstack.getMemberJSON();
      let metadata = memberJson.data || {};

      // Ensure userVisits exists as an array
      metadata.userVisits = Array.isArray(metadata.userVisits) ? metadata.userVisits : [];

      // Use ISO date (YYYY-MM-DD) to record one visit per day
      const today = new Date().toISOString().split("T")[0];
      if (!metadata.userVisits.includes(today)) {
        metadata.userVisits.push(today);
      }

      // Helper: Compute consecutive login streak from userVisits
      function computeStreak(visits) {
        if (!visits.length) return 0;
        // Ensure dates are unique and sorted ascending
        const uniqueVisits = [...new Set(visits)].sort();
        let streak = 1;
        let currentDate = new Date(uniqueVisits[uniqueVisits.length - 1]);
        for (let i = uniqueVisits.length - 2; i >= 0; i--) {
          const prevDate = new Date(uniqueVisits[i]);
          const diffDays = Math.floor((currentDate - prevDate) / (1000 * 60 * 60 * 24));
          if (diffDays === 1) {
            streak++;
            currentDate = prevDate;
          } else {
            break;
          }
        }
        return streak;
      }

      // Calculate the login streak and total visits
      metadata.loginStreak = computeStreak(metadata.userVisits);
      metadata.totalVisits = metadata.userVisits.length;

      // Update Memberstack metadata
      await memberstack.updateMemberJSON({ json: metadata });

      console.log("User visits:", metadata.userVisits);
      console.log("Login streak:", metadata.loginStreak);
      console.log("Total visits:", metadata.totalVisits);
    }

    onMemberstackReady(initTracking);
  })();
</script>
Ansicht Memberscript
UX
Marketing

#143 - Initial Based Profile Avatar

Generate a custom avatar with initials when a member has no profile picture.


<!-- 💙 MEMBERSCRIPT #143 v0.1 💙 - GENERATE INITIALS BASED AVATAR -->
<script>
  document.addEventListener("DOMContentLoaded", function () {
    const checkMemberstack = setInterval(() => {
      if (window.$memberstackDom) {
        clearInterval(checkMemberstack);

        window.$memberstackDom.getCurrentMember().then(({ data }) => {
          if (!data) return console.log("No member data (logged out)");

          const profileImage = document.querySelector('[data-ms-member="profile-image"]');
          const avatarWrapper = document.querySelector('[data-ms-code="avatar"]');
          const initialsDiv = avatarWrapper?.querySelector('.ms-avatar-initial');

          if (data.profileImage) {
            profileImage?.style.setProperty("display", "block");
            avatarWrapper?.style.setProperty("display", "none");
          } else {
            profileImage?.style.setProperty("display", "none");
            avatarWrapper?.style.setProperty("display", "flex");

            // Get initials from available fields
            const first = data.customFields["first-name"]?.trim().charAt(0).toUpperCase() || "";
            const last = data.customFields["last-name"]?.trim().charAt(0).toUpperCase() || "";
            let initials = first + last;

            if (!initials) {
              const fullName = data.customFields["name"]?.trim().split(" ") || [];
              initials = fullName.length > 1
                ? (fullName[0].charAt(0) + fullName[1].charAt(0)).toUpperCase()
                : fullName[0]?.charAt(0).toUpperCase() || "?";
            }

            if (initialsDiv) {
              initialsDiv.textContent = initials;
            } else {
              avatarWrapper.innerHTML = `
${initials}
`; } } }).catch(console.error); } }, 100); }); </script>
v0.1

<!-- 💙 MEMBERSCRIPT #143 v0.1 💙 - GENERATE INITIALS BASED AVATAR -->
<script>
  document.addEventListener("DOMContentLoaded", function () {
    const checkMemberstack = setInterval(() => {
      if (window.$memberstackDom) {
        clearInterval(checkMemberstack);

        window.$memberstackDom.getCurrentMember().then(({ data }) => {
          if (!data) return console.log("No member data (logged out)");

          const profileImage = document.querySelector('[data-ms-member="profile-image"]');
          const avatarWrapper = document.querySelector('[data-ms-code="avatar"]');
          const initialsDiv = avatarWrapper?.querySelector('.ms-avatar-initial');

          if (data.profileImage) {
            profileImage?.style.setProperty("display", "block");
            avatarWrapper?.style.setProperty("display", "none");
          } else {
            profileImage?.style.setProperty("display", "none");
            avatarWrapper?.style.setProperty("display", "flex");

            // Get initials from available fields
            const first = data.customFields["first-name"]?.trim().charAt(0).toUpperCase() || "";
            const last = data.customFields["last-name"]?.trim().charAt(0).toUpperCase() || "";
            let initials = first + last;

            if (!initials) {
              const fullName = data.customFields["name"]?.trim().split(" ") || [];
              initials = fullName.length > 1
                ? (fullName[0].charAt(0) + fullName[1].charAt(0)).toUpperCase()
                : fullName[0]?.charAt(0).toUpperCase() || "?";
            }

            if (initialsDiv) {
              initialsDiv.textContent = initials;
            } else {
              avatarWrapper.innerHTML = `
${initials}
`; } } }).catch(console.error); } }, 100); }); </script>
Ansicht Memberscript
UX
Marketing

#142 - Embed PDFs For Webflow

Easily embed a PDF on your Webflow site - for free, without any custom code.


<!-- 💙 MEMBERSCRIPT #142 v0.1 💙 - EMBED PDFS IN WEBFLOW -->
<script>
  document.addEventListener("DOMContentLoaded", function () {
    const pdfElements = document.querySelectorAll('[ms-code-pdf-src]');

    pdfElements.forEach(function (element) {
      const src = element.getAttribute('ms-code-pdf-src');
      const height = element.getAttribute('ms-code-pdf-height') || '500px';

      const iframe = document.createElement('iframe');
      iframe.src = src;
      iframe.style.width = '100%';
      iframe.style.height = height;
      iframe.style.border = 'none';
      // Set the iframe to block to remove any inline element gaps
      iframe.style.display = 'block';
      iframe.setAttribute('scrolling', 'auto');

      element.innerHTML = '';
      element.appendChild(iframe);
    });
  });
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #142 v0.1 💙 - EMBED PDFS IN WEBFLOW -->
<script>
  document.addEventListener("DOMContentLoaded", function () {
    const pdfElements = document.querySelectorAll('[ms-code-pdf-src]');

    pdfElements.forEach(function (element) {
      const src = element.getAttribute('ms-code-pdf-src');
      const height = element.getAttribute('ms-code-pdf-height') || '500px';

      const iframe = document.createElement('iframe');
      iframe.src = src;
      iframe.style.width = '100%';
      iframe.style.height = height;
      iframe.style.border = 'none';
      // Set the iframe to block to remove any inline element gaps
      iframe.style.display = 'block';
      iframe.setAttribute('scrolling', 'auto');

      element.innerHTML = '';
      element.appendChild(iframe);
    });
  });
</script>
Ansicht Memberscript
UX
Marketing

#Nr. 141 - YouTube-Einbettung zu einer bestimmten Zeit starten

Aktivieren Sie teilbare Links und starten Sie die Wiedergabe von Videos zu einer bestimmten Zeit.


<!-- 💙 MEMBERSCRIPT #141 v0.1 💙 - START YOUTUBE VIDEO AT SPECIFIC TIME -->
<script>
  (function() {
    // Function to get URL parameters
    function getUrlParameter(name) {
      name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
      var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
      var results = regex.exec(location.search);
      return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
    }

    // Function to update YouTube embed src within Embedly iframe
    function updateYouTubeEmbed(embedly_iframe, startTime) {
      var embedly_src = embedly_iframe.src;
      var youtube_src_match = embedly_src.match(/src=([^&]+)/);
      if (youtube_src_match) {
        var youtube_src = decodeURIComponent(youtube_src_match[1]);
        var new_youtube_src = youtube_src.replace(/(\?|&)start=\d+/, '');
        new_youtube_src += (new_youtube_src.includes('?') ? '&' : '?') + 'start=' + startTime;
        var new_embedly_src = embedly_src.replace(/src=([^&]+)/, 'src=' + encodeURIComponent(new_youtube_src));
        embedly_iframe.src = new_embedly_src;
      }
    }

    // Get all elements with ms-code-yt-start attribute
    var elements = document.querySelectorAll('[ms-code-yt-start]');

    elements.forEach(function(element) {
      var paramName = element.getAttribute('ms-code-yt-start');
      var startTime = getUrlParameter(paramName);
      var defaultStartTime = element.getAttribute('ms-code-yt-start-default');

      // If no URL parameter, use the default start time (if specified)
      if (!startTime && defaultStartTime) {
        startTime = defaultStartTime;
      }

      // If we have a start time (either from URL or default), update the embed
      if (startTime) {
        var iframe = element.querySelector('iframe.embedly-embed');
        if (iframe) {
          updateYouTubeEmbed(iframe, startTime);
        }
      }
    });
  })();
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #141 v0.1 💙 - START YOUTUBE VIDEO AT SPECIFIC TIME -->
<script>
  (function() {
    // Function to get URL parameters
    function getUrlParameter(name) {
      name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
      var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
      var results = regex.exec(location.search);
      return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
    }

    // Function to update YouTube embed src within Embedly iframe
    function updateYouTubeEmbed(embedly_iframe, startTime) {
      var embedly_src = embedly_iframe.src;
      var youtube_src_match = embedly_src.match(/src=([^&]+)/);
      if (youtube_src_match) {
        var youtube_src = decodeURIComponent(youtube_src_match[1]);
        var new_youtube_src = youtube_src.replace(/(\?|&)start=\d+/, '');
        new_youtube_src += (new_youtube_src.includes('?') ? '&' : '?') + 'start=' + startTime;
        var new_embedly_src = embedly_src.replace(/src=([^&]+)/, 'src=' + encodeURIComponent(new_youtube_src));
        embedly_iframe.src = new_embedly_src;
      }
    }

    // Get all elements with ms-code-yt-start attribute
    var elements = document.querySelectorAll('[ms-code-yt-start]');

    elements.forEach(function(element) {
      var paramName = element.getAttribute('ms-code-yt-start');
      var startTime = getUrlParameter(paramName);
      var defaultStartTime = element.getAttribute('ms-code-yt-start-default');

      // If no URL parameter, use the default start time (if specified)
      if (!startTime && defaultStartTime) {
        startTime = defaultStartTime;
      }

      // If we have a start time (either from URL or default), update the embed
      if (startTime) {
        var iframe = element.querySelector('iframe.embedly-embed');
        if (iframe) {
          updateYouTubeEmbed(iframe, startTime);
        }
      }
    });
  })();
</script>
Ansicht Memberscript
Benutzerdefinierte Abläufe
UX

#140 - Bestätigung der übereinstimmenden Eingaben

Überprüfen Sie eine Eingabe, bevor Sie die Übermittlung zulassen - dies ist wichtig, um falsche Angaben zu vermeiden!


<!-- 💙 MEMBERSCRIPT #140 v0.1 💙 - CONFIRM MATCHING INPUTS -->
<script>
  document.addEventListener('DOMContentLoaded', function() {
    const forms = document.querySelectorAll('form');

    forms.forEach(form => {
      const inputPairs = form.querySelectorAll('[ms-code-conf-input]');
      const submitButton = form.querySelector('input[type="submit"], button[type="submit"]');

      if (!submitButton) {
        console.error('Submit button not found in the form');
        return;
      }

      function validateForm() {
        let fieldsMatch = true;

        inputPairs.forEach(input => {
          const confType = input.getAttribute('ms-code-conf-input');
          const confirmInput = form.querySelector(`[ms-code-conf="${confType}"]`);
          const errorElement = form.querySelector(`[ms-code-conf-error="${confType}"]`);

          if (confirmInput && errorElement) {
            if (input.value && confirmInput.value) {
              if (input.value !== confirmInput.value) {
                errorElement.style.removeProperty('display');
                fieldsMatch = false;
              } else {
                errorElement.style.display = 'none';
              }
            } else {
              errorElement.style.display = 'none';
            }
          }
        });

        if (fieldsMatch) {
          submitButton.style.removeProperty('pointer-events');
          submitButton.disabled = false;
        } else {
          submitButton.style.pointerEvents = 'none';
          submitButton.disabled = true;
        }
      }

      inputPairs.forEach(input => {
        const confType = input.getAttribute('ms-code-conf-input');
        const confirmInput = form.querySelector(`[ms-code-conf="${confType}"]`);

        if (confirmInput) {
          input.addEventListener('input', validateForm);
          confirmInput.addEventListener('input', validateForm);
        }
      });

      // Initial validation
      validateForm();

      // Extra precaution: prevent form submission if fields don't match
      form.addEventListener('submit', function(event) {
        if (submitButton.disabled) {
          event.preventDefault();
          console.log('Form submission blocked: Fields do not match');
        }
      });
    });
  });
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #140 v0.1 💙 - CONFIRM MATCHING INPUTS -->
<script>
  document.addEventListener('DOMContentLoaded', function() {
    const forms = document.querySelectorAll('form');

    forms.forEach(form => {
      const inputPairs = form.querySelectorAll('[ms-code-conf-input]');
      const submitButton = form.querySelector('input[type="submit"], button[type="submit"]');

      if (!submitButton) {
        console.error('Submit button not found in the form');
        return;
      }

      function validateForm() {
        let fieldsMatch = true;

        inputPairs.forEach(input => {
          const confType = input.getAttribute('ms-code-conf-input');
          const confirmInput = form.querySelector(`[ms-code-conf="${confType}"]`);
          const errorElement = form.querySelector(`[ms-code-conf-error="${confType}"]`);

          if (confirmInput && errorElement) {
            if (input.value && confirmInput.value) {
              if (input.value !== confirmInput.value) {
                errorElement.style.removeProperty('display');
                fieldsMatch = false;
              } else {
                errorElement.style.display = 'none';
              }
            } else {
              errorElement.style.display = 'none';
            }
          }
        });

        if (fieldsMatch) {
          submitButton.style.removeProperty('pointer-events');
          submitButton.disabled = false;
        } else {
          submitButton.style.pointerEvents = 'none';
          submitButton.disabled = true;
        }
      }

      inputPairs.forEach(input => {
        const confType = input.getAttribute('ms-code-conf-input');
        const confirmInput = form.querySelector(`[ms-code-conf="${confType}"]`);

        if (confirmInput) {
          input.addEventListener('input', validateForm);
          confirmInput.addEventListener('input', validateForm);
        }
      });

      // Initial validation
      validateForm();

      // Extra precaution: prevent form submission if fields don't match
      form.addEventListener('submit', function(event) {
        if (submitButton.disabled) {
          event.preventDefault();
          console.log('Form submission blocked: Fields do not match');
        }
      });
    });
  });
</script>
Ansicht Memberscript
UX

#Nr. 139 - Formular nach Übermittlung zurücksetzen

Erstellen Sie im Erfolgszustand des Formulars eine Schaltfläche, mit der das Formular erneut eingereicht werden kann.


<!-- 💙 MEMBERSCRIPT #139 v0.1 💙 - RESET FORM BUTTON -->
<script>
  // Wait for the DOM to be fully loaded
  document.addEventListener('DOMContentLoaded', function() {
    // Find all "Add another" buttons
    const resetButtons = document.querySelectorAll('[ms-code-reset-form]');

    // Add click event listener to each button
    resetButtons.forEach(function(resetButton) {
      resetButton.addEventListener('click', function(e) {
        e.preventDefault(); // Prevent default link behavior

        // Find the closest form and success message elements
        const formWrapper = this.closest('.w-form');
        const form = formWrapper.querySelector('form');
        const successMessage = formWrapper.querySelector('.w-form-done');

        // Reset the form
        form.reset();

        // Hide the success message
        successMessage.style.display = 'none';

        // Show the form
        form.style.display = 'block';
      });
    });
  });
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #139 v0.1 💙 - RESET FORM BUTTON -->
<script>
  // Wait for the DOM to be fully loaded
  document.addEventListener('DOMContentLoaded', function() {
    // Find all "Add another" buttons
    const resetButtons = document.querySelectorAll('[ms-code-reset-form]');

    // Add click event listener to each button
    resetButtons.forEach(function(resetButton) {
      resetButton.addEventListener('click', function(e) {
        e.preventDefault(); // Prevent default link behavior

        // Find the closest form and success message elements
        const formWrapper = this.closest('.w-form');
        const form = formWrapper.querySelector('form');
        const successMessage = formWrapper.querySelector('.w-form-done');

        // Reset the form
        form.reset();

        // Hide the success message
        successMessage.style.display = 'none';

        // Show the form
        form.style.display = 'block';
      });
    });
  });
</script>
Ansicht Memberscript
UX

#Nr. 138 - Anker Link Scroll Offset

Behebung des Problems mit Ankerlinks und klebrigen/fixierten Navigationsleisten in Webflow.


<!-- 💙 MEMBERSCRIPT #138 v0.1 💙 - ANCHOR LINK SCROLL OFFSET -->
<script>
  // Disable Webflow's built-in smooth scrolling
  var Webflow = Webflow || [];
  Webflow.push(function() {
    $(function() { 
      $(document).off('click.wf-scroll');
    });
  });

  // Smooth scroll implementation with customizable settings
  (function() {
    // Customizable settings
    const SCROLL_SETTINGS = {
      duration: 1000, // in milliseconds
      easing: 'easeInOutCubic' // 'linear', 'easeInQuad', 'easeOutQuad', 'easeInOutQuad', 'easeInCubic', 'easeOutCubic', 'easeInOutCubic'
    };

    const EASING_FUNCTIONS = {
      linear: t => t,
      easeInQuad: t => t * t,
      easeOutQuad: t => t * (2 - t),
      easeInOutQuad: t => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
      easeInCubic: t => t * t * t,
      easeOutCubic: t => (--t) * t * t + 1,
      easeInOutCubic: t => t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1
    };

    function getOffset() {
      const navbar = document.querySelector('[ms-code-scroll-offset]');
      if (!navbar) return 0;
      const navbarHeight = navbar.offsetHeight;
      const customOffset = parseInt(navbar.getAttribute('ms-code-scroll-offset') || '0', 10);
      return navbarHeight + customOffset;
    }

    function smoothScroll(target) {
      const startPosition = window.pageYOffset;
      const offset = getOffset();
      const targetPosition = target.getBoundingClientRect().top + startPosition - offset;
      const distance = targetPosition - startPosition;
      let startTime = null;

      function animation(currentTime) {
        if (startTime === null) startTime = currentTime;
        const timeElapsed = currentTime - startTime;
        const progress = Math.min(timeElapsed / SCROLL_SETTINGS.duration, 1);
        const easeProgress = EASING_FUNCTIONS[SCROLL_SETTINGS.easing](progress);
        window.scrollTo(0, startPosition + distance * easeProgress);
        if (timeElapsed < SCROLL_SETTINGS.duration) requestAnimationFrame(animation);
      }

      requestAnimationFrame(animation);
    }

    function handleClick(e) {
      const href = e.currentTarget.getAttribute('href');
      if (href.startsWith('#')) {
        e.preventDefault();
        const target = document.getElementById(href.slice(1));
        if (target) smoothScroll(target);
      }
    }

    function handleHashChange() {
      if (window.location.hash) {
        const target = document.getElementById(window.location.hash.slice(1));
        if (target) {
          setTimeout(() => smoothScroll(target), 0);
        }
      }
    }

    function init() {
      document.querySelectorAll('a[href^="#"]').forEach(anchor => {
        anchor.addEventListener('click', handleClick);
      });
      window.addEventListener('hashchange', handleHashChange);
      handleHashChange(); // Handle initial hash on page load
    }

    document.addEventListener('DOMContentLoaded', init);
    window.Webflow && window.Webflow.push(init);
  })();
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #138 v0.1 💙 - ANCHOR LINK SCROLL OFFSET -->
<script>
  // Disable Webflow's built-in smooth scrolling
  var Webflow = Webflow || [];
  Webflow.push(function() {
    $(function() { 
      $(document).off('click.wf-scroll');
    });
  });

  // Smooth scroll implementation with customizable settings
  (function() {
    // Customizable settings
    const SCROLL_SETTINGS = {
      duration: 1000, // in milliseconds
      easing: 'easeInOutCubic' // 'linear', 'easeInQuad', 'easeOutQuad', 'easeInOutQuad', 'easeInCubic', 'easeOutCubic', 'easeInOutCubic'
    };

    const EASING_FUNCTIONS = {
      linear: t => t,
      easeInQuad: t => t * t,
      easeOutQuad: t => t * (2 - t),
      easeInOutQuad: t => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
      easeInCubic: t => t * t * t,
      easeOutCubic: t => (--t) * t * t + 1,
      easeInOutCubic: t => t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1
    };

    function getOffset() {
      const navbar = document.querySelector('[ms-code-scroll-offset]');
      if (!navbar) return 0;
      const navbarHeight = navbar.offsetHeight;
      const customOffset = parseInt(navbar.getAttribute('ms-code-scroll-offset') || '0', 10);
      return navbarHeight + customOffset;
    }

    function smoothScroll(target) {
      const startPosition = window.pageYOffset;
      const offset = getOffset();
      const targetPosition = target.getBoundingClientRect().top + startPosition - offset;
      const distance = targetPosition - startPosition;
      let startTime = null;

      function animation(currentTime) {
        if (startTime === null) startTime = currentTime;
        const timeElapsed = currentTime - startTime;
        const progress = Math.min(timeElapsed / SCROLL_SETTINGS.duration, 1);
        const easeProgress = EASING_FUNCTIONS[SCROLL_SETTINGS.easing](progress);
        window.scrollTo(0, startPosition + distance * easeProgress);
        if (timeElapsed < SCROLL_SETTINGS.duration) requestAnimationFrame(animation);
      }

      requestAnimationFrame(animation);
    }

    function handleClick(e) {
      const href = e.currentTarget.getAttribute('href');
      if (href.startsWith('#')) {
        e.preventDefault();
        const target = document.getElementById(href.slice(1));
        if (target) smoothScroll(target);
      }
    }

    function handleHashChange() {
      if (window.location.hash) {
        const target = document.getElementById(window.location.hash.slice(1));
        if (target) {
          setTimeout(() => smoothScroll(target), 0);
        }
      }
    }

    function init() {
      document.querySelectorAll('a[href^="#"]').forEach(anchor => {
        anchor.addEventListener('click', handleClick);
      });
      window.addEventListener('hashchange', handleHashChange);
      handleHashChange(); // Handle initial hash on page load
    }

    document.addEventListener('DOMContentLoaded', init);
    window.Webflow && window.Webflow.push(init);
  })();
</script>
Ansicht Memberscript
UX

#Nr. 137 - Anzeige des Namens des Besucherlandes

Ersetzen Sie den Text durch das Land, in dem sich ein Benutzer auf der Grundlage seiner IP-Adresse befindet.


<!-- 💙 MEMBERSCRIPT #137 v0.1 💙 - DISPLAY COUNTRY NAME -->
<script>
  document.addEventListener('DOMContentLoaded', function() {
    fetch('https://ipapi.co/json/')
      .then(response => response.json())
      .then(data => {
        if (data.country_name) {
          const countryElements = document.querySelectorAll('[ms-code-display-country]');
          countryElements.forEach(element => {
            element.textContent = data.country_name;
          });
        }
      })
      .catch(error => {
        console.error('Error fetching country:', error);
      });
  });
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #137 v0.1 💙 - DISPLAY COUNTRY NAME -->
<script>
  document.addEventListener('DOMContentLoaded', function() {
    fetch('https://ipapi.co/json/')
      .then(response => response.json())
      .then(data => {
        if (data.country_name) {
          const countryElements = document.querySelectorAll('[ms-code-display-country]');
          countryElements.forEach(element => {
            element.textContent = data.country_name;
          });
        }
      })
      .catch(error => {
        console.error('Error fetching country:', error);
      });
  });
</script>
Ansicht Memberscript
UX

#Nr. 136 - Abschnittspfad aus URL entfernen

Wenn zu einem Abschnitt navigiert wird, wird der Pfad des Ankerlinks entfernt.


<!-- 💙 MEMBERSCRIPT #136 💙 REMOVE SECTION PATH FROM URL -->
<script>
document.addEventListener('DOMContentLoaded', function() {
    // Check if there's a hash in the URL
    if (window.location.hash) {
        // Get the target element
        const targetId = window.location.hash.substring(1);
        const targetElement = document.getElementById(targetId);

        if (targetElement) {
            // Scroll to the target element
            targetElement.scrollIntoView({behavior: 'smooth'});

            // Remove the hash after a short delay (to allow scrolling to complete)
            setTimeout(function() {
                history.pushState("", document.title, window.location.pathname + window.location.search);
            }, 100);
        }
    }

    // Add click event listeners to all internal links
    document.querySelectorAll('a[href^="#"]').forEach(anchor => {
        anchor.addEventListener('click', function(e) {
            e.preventDefault();

            const targetId = this.getAttribute('href').substring(1);
            const targetElement = document.getElementById(targetId);

            if (targetElement) {
                targetElement.scrollIntoView({behavior: 'smooth'});

                // Remove the hash after a short delay (to allow scrolling to complete)
                setTimeout(function() {
                    history.pushState("", document.title, window.location.pathname + window.location.search);
                }, 100);
            }
        });
    });
});
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #136 💙 REMOVE SECTION PATH FROM URL -->
<script>
document.addEventListener('DOMContentLoaded', function() {
    // Check if there's a hash in the URL
    if (window.location.hash) {
        // Get the target element
        const targetId = window.location.hash.substring(1);
        const targetElement = document.getElementById(targetId);

        if (targetElement) {
            // Scroll to the target element
            targetElement.scrollIntoView({behavior: 'smooth'});

            // Remove the hash after a short delay (to allow scrolling to complete)
            setTimeout(function() {
                history.pushState("", document.title, window.location.pathname + window.location.search);
            }, 100);
        }
    }

    // Add click event listeners to all internal links
    document.querySelectorAll('a[href^="#"]').forEach(anchor => {
        anchor.addEventListener('click', function(e) {
            e.preventDefault();

            const targetId = this.getAttribute('href').substring(1);
            const targetElement = document.getElementById(targetId);

            if (targetElement) {
                targetElement.scrollIntoView({behavior: 'smooth'});

                // Remove the hash after a short delay (to allow scrolling to complete)
                setTimeout(function() {
                    history.pushState("", document.title, window.location.pathname + window.location.search);
                }, 100);
            }
        });
    });
});
</script>
Ansicht Memberscript
Benutzerdefinierte Abläufe

#Nr. 135 - Umleitung auf Basis eines ausgewählten Wertes

Legen Sie die Umleitung des Formulars dynamisch auf der Grundlage der Benutzerauswahl fest.


<!-- 💙 MEMBERSCRIPT #135 v0.2 💙 - REDIRECT FORM FROM SELECT VALUE -->
<script>
  (function() {
    'use strict';

    function initDropdownRedirect() {
      const dropdown = document.querySelector('select[ms-code-dropdown-redirect]');
      if (!dropdown) return;

      const form = dropdown.closest('form');
      if (!form) return;

      function updateRedirect() {
        const selectedValue = dropdown.value;
        form.setAttribute('redirect', selectedValue);
        form.setAttribute('data-redirect', selectedValue);
      }

      function handleSubmit(event) {
        event.preventDefault();
        const redirectUrl = form.getAttribute('data-redirect') || form.getAttribute('redirect');
        if (redirectUrl) {
          setTimeout(() => {
            window.location.href = redirectUrl;
          }, 500); // Delay redirect by 500 milliseconds
        } else {
          form.submit(); // Fall back to normal form submission if no redirect is set
        }
      }


      dropdown.addEventListener('change', updateRedirect);
      form.addEventListener('submit', handleSubmit);

      // Initialize redirect on page load
      updateRedirect();
    }

    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', initDropdownRedirect);
    } else {
      initDropdownRedirect();
    }
  })();
</script>
v0.2

<!-- 💙 MEMBERSCRIPT #135 v0.2 💙 - REDIRECT FORM FROM SELECT VALUE -->
<script>
  (function() {
    'use strict';

    function initDropdownRedirect() {
      const dropdown = document.querySelector('select[ms-code-dropdown-redirect]');
      if (!dropdown) return;

      const form = dropdown.closest('form');
      if (!form) return;

      function updateRedirect() {
        const selectedValue = dropdown.value;
        form.setAttribute('redirect', selectedValue);
        form.setAttribute('data-redirect', selectedValue);
      }

      function handleSubmit(event) {
        event.preventDefault();
        const redirectUrl = form.getAttribute('data-redirect') || form.getAttribute('redirect');
        if (redirectUrl) {
          setTimeout(() => {
            window.location.href = redirectUrl;
          }, 500); // Delay redirect by 500 milliseconds
        } else {
          form.submit(); // Fall back to normal form submission if no redirect is set
        }
      }


      dropdown.addEventListener('change', updateRedirect);
      form.addEventListener('submit', handleSubmit);

      // Initialize redirect on page load
      updateRedirect();
    }

    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', initDropdownRedirect);
    } else {
      initDropdownRedirect();
    }
  })();
</script>
Ansicht Memberscript
UX

#Nr. 134 - Nach oben scrollen bei Tabwechsel

Wenn die Registerkarte gewechselt wird, blättert die Seite an den Anfang des Registerkartenbereichs.


<!-- 💙 MEMBERSCRIPT #134 💙 - SCROLL TO TOP OF TABS ON CHANGE -->
<script>
  document.addEventListener('DOMContentLoaded', function() {
    // Select all tab containers with the ms-code-tab-scroll-top attribute
    const tabContainers = document.querySelectorAll('.w-tabs[ms-code-tab-scroll-top]');

    tabContainers.forEach(container => {
      const tabLinks = container.querySelectorAll('.w-tab-link');
      const scrollTopValue = parseInt(container.getAttribute('ms-code-tab-scroll-top') || '0');

      tabLinks.forEach(link => {
        link.addEventListener('click', function(e) {
          // Small delay to ensure the new tab content is rendered
          setTimeout(() => {
            // Find the active tab pane within this container
            const activePane = container.querySelector('.w-tab-pane.w--tab-active');

            if (activePane) {
              // Calculate the new scroll position
              const newScrollPosition = container.getBoundingClientRect().top + window.pageYOffset + scrollTopValue;

              // Scroll to the new position
              window.scrollTo({
                top: newScrollPosition,
                behavior: 'smooth'
              });
            }
          }, 50); // 50ms delay, adjust if needed
        });
      });
    });
  });
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #134 💙 - SCROLL TO TOP OF TABS ON CHANGE -->
<script>
  document.addEventListener('DOMContentLoaded', function() {
    // Select all tab containers with the ms-code-tab-scroll-top attribute
    const tabContainers = document.querySelectorAll('.w-tabs[ms-code-tab-scroll-top]');

    tabContainers.forEach(container => {
      const tabLinks = container.querySelectorAll('.w-tab-link');
      const scrollTopValue = parseInt(container.getAttribute('ms-code-tab-scroll-top') || '0');

      tabLinks.forEach(link => {
        link.addEventListener('click', function(e) {
          // Small delay to ensure the new tab content is rendered
          setTimeout(() => {
            // Find the active tab pane within this container
            const activePane = container.querySelector('.w-tab-pane.w--tab-active');

            if (activePane) {
              // Calculate the new scroll position
              const newScrollPosition = container.getBoundingClientRect().top + window.pageYOffset + scrollTopValue;

              // Scroll to the new position
              window.scrollTo({
                top: newScrollPosition,
                behavior: 'smooth'
              });
            }
          }, 50); // 50ms delay, adjust if needed
        });
      });
    });
  });
</script>
Ansicht Memberscript
Sicherheit

#Nr. 133 - Automatisches Wasserzeichen für Bilder

Fügen Sie den Bildern auf Ihrer Webflow-Website ganz einfach ein Wasserzeichen hinzu.


<!-- 💙 MEMBERSCRIPT #133 v0.1 💙 - AUTO IMAGE WATERMARK -->
<script>
  function addWatermarkToImages() {
    const images = document.querySelectorAll('img[ms-code-watermark]');

    images.forEach(img => {
      img.crossOrigin = "Anonymous";  // This allows us to work with images from other domains
      img.onload = function() {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');

        // Set canvas size to match the image
        canvas.width = img.width;
        canvas.height = img.height;

        // Draw the original image onto the canvas
        ctx.drawImage(img, 0, 0, img.width, img.height);

        // Get watermark text from attribute
        const watermarkText = img.getAttribute('ms-code-watermark') || 'Watermark';

        // Add watermark
        ctx.font = `${img.width / 20}px Arial`;  // Adjust font size based on image width
        ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';

        // Rotate and draw the watermark text
        ctx.save();
        ctx.translate(canvas.width / 2, canvas.height / 2);
        ctx.rotate(-Math.PI / 4);  // Rotate 45 degrees
        ctx.fillText(watermarkText, 0, 0);
        ctx.restore();

        // Preserve the original image's classes and other attributes
        canvas.className = img.className;
        for (let i = 0; i < img.attributes.length; i++) {
          const attr = img.attributes[i];
          if (attr.name !== 'src' && attr.name !== 'ms-code-watermark') {
            canvas.setAttribute(attr.name, attr.value);
          }
        }

        // Replace the original image with the watermarked canvas
        img.parentNode.replaceChild(canvas, img);
      };

      // Trigger onload event (in case the image is already loaded)
      if (img.complete) {
        img.onload();
      }
    });
  }

  // Run the function when the DOM is fully loaded
  document.addEventListener('DOMContentLoaded', addWatermarkToImages);
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #133 v0.1 💙 - AUTO IMAGE WATERMARK -->
<script>
  function addWatermarkToImages() {
    const images = document.querySelectorAll('img[ms-code-watermark]');

    images.forEach(img => {
      img.crossOrigin = "Anonymous";  // This allows us to work with images from other domains
      img.onload = function() {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');

        // Set canvas size to match the image
        canvas.width = img.width;
        canvas.height = img.height;

        // Draw the original image onto the canvas
        ctx.drawImage(img, 0, 0, img.width, img.height);

        // Get watermark text from attribute
        const watermarkText = img.getAttribute('ms-code-watermark') || 'Watermark';

        // Add watermark
        ctx.font = `${img.width / 20}px Arial`;  // Adjust font size based on image width
        ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';

        // Rotate and draw the watermark text
        ctx.save();
        ctx.translate(canvas.width / 2, canvas.height / 2);
        ctx.rotate(-Math.PI / 4);  // Rotate 45 degrees
        ctx.fillText(watermarkText, 0, 0);
        ctx.restore();

        // Preserve the original image's classes and other attributes
        canvas.className = img.className;
        for (let i = 0; i < img.attributes.length; i++) {
          const attr = img.attributes[i];
          if (attr.name !== 'src' && attr.name !== 'ms-code-watermark') {
            canvas.setAttribute(attr.name, attr.value);
          }
        }

        // Replace the original image with the watermarked canvas
        img.parentNode.replaceChild(canvas, img);
      };

      // Trigger onload event (in case the image is already loaded)
      if (img.complete) {
        img.onload();
      }
    });
  }

  // Run the function when the DOM is fully loaded
  document.addEventListener('DOMContentLoaded', addWatermarkToImages);
</script>
Ansicht Memberscript
Erreichbarkeit
Modale

#Nr. 132 - Elemente mit der Escape-Taste ausblenden

Fügen Sie ein Attribut hinzu, und wenn die Taste esc angeklickt wird, wird das Element auf "none" gesetzt.


<!-- 💙 MEMBERSCRIPT 💙 - HIDE ELEMENTS WITH ESC KEY -->
<script>
  document.addEventListener('keydown', function(event) {
    // Check if the pressed key is ESC (key code 27)
    if (event.key === 'Escape' || event.keyCode === 27) {
      // Find all elements with the attribute ms-code-close-esc
      const elements = document.querySelectorAll('[ms-code-close-esc]');

      // Loop through the elements and set their display to 'none'
      elements.forEach(function(element) {
        element.style.display = 'none';
      });
    }
  });
</script>
v0.1

<!-- 💙 MEMBERSCRIPT 💙 - HIDE ELEMENTS WITH ESC KEY -->
<script>
  document.addEventListener('keydown', function(event) {
    // Check if the pressed key is ESC (key code 27)
    if (event.key === 'Escape' || event.keyCode === 27) {
      // Find all elements with the attribute ms-code-close-esc
      const elements = document.querySelectorAll('[ms-code-close-esc]');

      // Loop through the elements and set their display to 'none'
      elements.forEach(function(element) {
        element.style.display = 'none';
      });
    }
  });
</script>
Ansicht Memberscript
Benutzerdefinierte Felder

#Nr. 131 - Addition von Zahleneingaben

Nehmen Sie den Wert von Zahleneingaben und zeigen Sie ihn in einem Eingabewert oder in einem Textbereich an.


<!-- 💙 MEMBERSCRIPT #131 v0.1 💙 - CALCULATE NUMBER INPUTS -->
<script>
  // Function to initialize the counter functionality
  function initializeCounter() {
    const counters = {};

    // Find all elements with ms-code-show-number attribute
    document.querySelectorAll('[ms-code-show-number]').forEach(el => {
      const counterName = el.getAttribute('ms-code-show-number');
      if (!counters[counterName]) {
        counters[counterName] = { total: 0, displays: [] };
      }
      counters[counterName].displays.push(el);
    });

    // Find all input elements with ms-code-add-number attribute
    document.querySelectorAll('input[ms-code-add-number]').forEach(input => {
      const counterName = input.getAttribute('ms-code-add-number');
      if (counters[counterName]) {
        input.addEventListener('input', updateCounter);
      }
    });

    // Function to update counter when input changes
    function updateCounter(event) {
      const input = event.target;
      const counterName = input.getAttribute('ms-code-add-number');
      const counter = counters[counterName];

      if (counter) {
        counter.total = 0;
        document.querySelectorAll(`input[ms-code-add-number="${counterName}"]`).forEach(input => {
          counter.total += parseInt(input.value) || 0;
        });

        counter.displays.forEach(display => {
          if (display.tagName === 'INPUT') {
            display.value = counter.total;
          } else {
            display.textContent = counter.total;
          }
        });
      }
    }

    // Initial update for all counters
    Object.keys(counters).forEach(counterName => {
      const input = document.querySelector(`input[ms-code-add-number="${counterName}"]`);
      if (input) {
        input.dispatchEvent(new Event('input'));
      }
    });
  }

  // Run the initialization when the DOM is fully loaded
  document.addEventListener('DOMContentLoaded', initializeCounter);
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #131 v0.1 💙 - CALCULATE NUMBER INPUTS -->
<script>
  // Function to initialize the counter functionality
  function initializeCounter() {
    const counters = {};

    // Find all elements with ms-code-show-number attribute
    document.querySelectorAll('[ms-code-show-number]').forEach(el => {
      const counterName = el.getAttribute('ms-code-show-number');
      if (!counters[counterName]) {
        counters[counterName] = { total: 0, displays: [] };
      }
      counters[counterName].displays.push(el);
    });

    // Find all input elements with ms-code-add-number attribute
    document.querySelectorAll('input[ms-code-add-number]').forEach(input => {
      const counterName = input.getAttribute('ms-code-add-number');
      if (counters[counterName]) {
        input.addEventListener('input', updateCounter);
      }
    });

    // Function to update counter when input changes
    function updateCounter(event) {
      const input = event.target;
      const counterName = input.getAttribute('ms-code-add-number');
      const counter = counters[counterName];

      if (counter) {
        counter.total = 0;
        document.querySelectorAll(`input[ms-code-add-number="${counterName}"]`).forEach(input => {
          counter.total += parseInt(input.value) || 0;
        });

        counter.displays.forEach(display => {
          if (display.tagName === 'INPUT') {
            display.value = counter.total;
          } else {
            display.textContent = counter.total;
          }
        });
      }
    }

    // Initial update for all counters
    Object.keys(counters).forEach(counterName => {
      const input = document.querySelector(`input[ms-code-add-number="${counterName}"]`);
      if (input) {
        input.dispatchEvent(new Event('input'));
      }
    });
  }

  // Run the initialization when the DOM is fully loaded
  document.addEventListener('DOMContentLoaded', initializeCounter);
</script>
Ansicht Memberscript
UX

#130 - Formular automatisch absenden, wenn sich alle Eingaben ändern

Überspringen Sie die Schaltfläche "Senden" und senden Sie das Formular, wenn sich alle Eingaben geändert haben.


<!-- 💙 MEMBERSCRIPT #130 v0.1 💙 - AUTO SUBMIT FORMS FROM INPUT CHANGE -->
<script>
  document.addEventListener('DOMContentLoaded', () => {
    const forms = document.querySelectorAll('form[ms-code-auto-submit]');

    forms.forEach(form => {
      const fields = form.querySelectorAll('input:not([type="submit"]):not([type="button"]):not([type="reset"]), select, textarea');
      const fieldStates = new Map(Array.from(fields).map(field => [field, false]));

      function updateFieldState(field, checkImmediately = false) {
        switch (field.type) {
          case 'checkbox':
            fieldStates.set(field, true); // Considered interacted with once changed
            break;
          case 'radio':
            const radioGroup = form.querySelectorAll(`input[type="radio"][name="${field.name}"]`);
            radioGroup.forEach(radio => fieldStates.set(radio, true));
            break;
          case 'select-one':
          case 'select-multiple':
            fieldStates.set(field, field.value !== '');
            break;
          case 'file':
            fieldStates.set(field, field.files.length > 0);
            break;
          case 'hidden':
            fieldStates.set(field, true); // Always consider hidden fields as filled
            break;
          default:
            // For text inputs, only update on blur or if checkImmediately is true
            if (field.type === 'text' || field.type === 'password' || field.type === 'email' || field.type === 'tel' || field.type === 'url' || field.tagName === 'TEXTAREA') {
              if (checkImmediately || !field.dataset.blurred) {
                fieldStates.set(field, field.value.trim() !== '');
              }
            } else {
              fieldStates.set(field, field.value.trim() !== '');
            }
        }
        if (checkImmediately) {
          checkAndSubmit();
        }
      }

      function checkAndSubmit() {
        if (Array.from(fieldStates.values()).every(state => state)) {
          // Create and dispatch a submit event
          const submitEvent = new Event('submit', {
            bubbles: true,
            cancelable: true
          });

          const submitted = form.dispatchEvent(submitEvent);

          // If the event wasn't prevented, manually submit the form
          if (submitted) {
            form.submit();
          }
        }
      }

      fields.forEach(field => {
        // Use 'change' event for checkboxes, radios, file inputs, and selects
        if (['checkbox', 'radio', 'file', 'select-one', 'select-multiple'].includes(field.type) || field.tagName === 'SELECT') {
          field.addEventListener('change', () => updateFieldState(field, true));
        }

        // For text-like inputs, use 'blur' event
        if (field.type === 'text' || field.type === 'password' || field.type === 'email' || field.type === 'tel' || field.type === 'url' || field.tagName === 'TEXTAREA') {
          field.addEventListener('blur', () => {
            field.dataset.blurred = 'true';
            updateFieldState(field, true);
          });
          // Also check on input, but don't submit immediately
          field.addEventListener('input', () => updateFieldState(field, false));
        }
      });

      // Initial check for pre-filled fields (e.g., browser autofill)
      fields.forEach(field => updateFieldState(field, false));
      checkAndSubmit();
    });
  });
</script>
v0.1

<!-- 💙 MEMBERSCRIPT #130 v0.1 💙 - AUTO SUBMIT FORMS FROM INPUT CHANGE -->
<script>
  document.addEventListener('DOMContentLoaded', () => {
    const forms = document.querySelectorAll('form[ms-code-auto-submit]');

    forms.forEach(form => {
      const fields = form.querySelectorAll('input:not([type="submit"]):not([type="button"]):not([type="reset"]), select, textarea');
      const fieldStates = new Map(Array.from(fields).map(field => [field, false]));

      function updateFieldState(field, checkImmediately = false) {
        switch (field.type) {
          case 'checkbox':
            fieldStates.set(field, true); // Considered interacted with once changed
            break;
          case 'radio':
            const radioGroup = form.querySelectorAll(`input[type="radio"][name="${field.name}"]`);
            radioGroup.forEach(radio => fieldStates.set(radio, true));
            break;
          case 'select-one':
          case 'select-multiple':
            fieldStates.set(field, field.value !== '');
            break;
          case 'file':
            fieldStates.set(field, field.files.length > 0);
            break;
          case 'hidden':
            fieldStates.set(field, true); // Always consider hidden fields as filled
            break;
          default:
            // For text inputs, only update on blur or if checkImmediately is true
            if (field.type === 'text' || field.type === 'password' || field.type === 'email' || field.type === 'tel' || field.type === 'url' || field.tagName === 'TEXTAREA') {
              if (checkImmediately || !field.dataset.blurred) {
                fieldStates.set(field, field.value.trim() !== '');
              }
            } else {
              fieldStates.set(field, field.value.trim() !== '');
            }
        }
        if (checkImmediately) {
          checkAndSubmit();
        }
      }

      function checkAndSubmit() {
        if (Array.from(fieldStates.values()).every(state => state)) {
          // Create and dispatch a submit event
          const submitEvent = new Event('submit', {
            bubbles: true,
            cancelable: true
          });

          const submitted = form.dispatchEvent(submitEvent);

          // If the event wasn't prevented, manually submit the form
          if (submitted) {
            form.submit();
          }
        }
      }

      fields.forEach(field => {
        // Use 'change' event for checkboxes, radios, file inputs, and selects
        if (['checkbox', 'radio', 'file', 'select-one', 'select-multiple'].includes(field.type) || field.tagName === 'SELECT') {
          field.addEventListener('change', () => updateFieldState(field, true));
        }

        // For text-like inputs, use 'blur' event
        if (field.type === 'text' || field.type === 'password' || field.type === 'email' || field.type === 'tel' || field.type === 'url' || field.tagName === 'TEXTAREA') {
          field.addEventListener('blur', () => {
            field.dataset.blurred = 'true';
            updateFieldState(field, true);
          });
          // Also check on input, but don't submit immediately
          field.addEventListener('input', () => updateFieldState(field, false));
        }
      });

      // Initial check for pre-filled fields (e.g., browser autofill)
      fields.forEach(field => updateFieldState(field, false));
      checkAndSubmit();
    });
  });
</script>
Ansicht Memberscript
Wir konnten keine Skripte für diese Suche finden... bitte versuchen Sie es erneut.
Slack

Brauchen Sie Hilfe mit MemberScripts? Treten Sie unserer Slack-Community mit über 5.500 Mitgliedern bei! 🙌

MemberScripts sind eine Community-Ressource von Memberstack - wenn du Hilfe brauchst, damit sie mit deinem Projekt funktionieren, melde dich bitte im Memberstack 2.0 Slack an und bitte um Hilfe!

Unserem Slack beitreten
Schaukasten

Entdecken Sie echte Unternehmen, die mit Memberstack erfolgreich waren

Verlassen Sie sich nicht nur auf unser Wort - schauen Sie sich die Unternehmen aller Größen an, die sich auf Memberstack für ihre Authentifizierung und Zahlungen verlassen.

Alle Erfolgsgeschichten anzeigen
Auch Webflow verwendet Memberstack!
Mit dem Bau beginnen

Bauen Sie Ihre Träume

Memberstack ist 100% kostenlos, bis Sie bereit sind, zu starten - worauf warten Sie also noch? Erstellen Sie Ihre erste App und beginnen Sie noch heute mit der Entwicklung.