Team Section CMS Modal

<script>
      (function ($) {
        // Modal control module
        const ModalController = {
          // Cache selectors
          elements: {
            wrapper: null,
            modals: null,
            cards: null,
            openTriggers: null,
            closeTriggers: null,
          },

          // Configuration
          config: {
            transitionDuration: 300,
            translateValue: '-100%',
            activeClass: 'hide',
          },

          // Initialize the module
          init: function () {
            this.cacheElements();
            this.setupInitialState();
            this.bindEvents();
          },

          // Cache DOM elements for performance
          cacheElements: function () {
            this.elements.wrapper = $('.team_modal-content');
            this.elements.modals = $('[data-modal="modal"]');
            this.elements.cards = $('.team_card');
            this.elements.openTriggers = $('[data-modal="open"]');
            this.elements.closeTriggers = $('[data-modal="close"]');
          },

          // Set up initial state
          setupInitialState: function () {
            // Hide all modals initially
            this.elements.modals.css({
              transform: `translateX(${this.config.translateValue})`,
              transition: `transform ${this.config.transitionDuration}ms ease-in-out`,
            });

            // Ensure modal wrapper has hide class
            this.elements.wrapper.addClass(this.config.activeClass);
          },

          // Bind all event listeners
          bindEvents: function () {
            // Open modal events
            $(document).on(
              'click',
              '[data-modal="open"]',
              this.handleOpenClick.bind(this)
            );

            // Close modal events
            $(document).on(
              'click',
              '[data-modal="close"]',
              this.handleCloseClick.bind(this)
            );

            // ESC key to close
            $(document).on('keyup', this.handleKeyup.bind(this));

            // Webflow interaction events
            $(document).on(
              'w-ix:click',
              this.handleWebflowInteraction.bind(this)
            );

            // Dynamic content updates
            $(document).on('w-dyn-list:updated', this.reInitialize.bind(this));

            // Team card clicks
            $(' [data-modal="open"]').on(
              'click',
              this.handleCardClick.bind(this)
            );
          },

          // Open modal by index
          openModal: function (index) {
            // Get the specific modal based on index
            const specificModal = this.elements.modals.eq(index);

            // Only proceed if we found a valid modal
            if (!this.elements.wrapper.length || !specificModal.length) {
              return;
            }

            // Reset all modals
            this.elements.modals.css(
              'transform',
              `translateX(${this.config.translateValue})`
            );

            // Show the wrapper
            this.elements.wrapper.removeClass(this.config.activeClass);

            // Force reflow
            void this.elements.wrapper[0].offsetHeight;

            // Slide in the specific modal
            specificModal.css('transform', 'translateX(0)');

            // Store current modal index
            this.elements.wrapper.data('current-modal', index);

            // Prevent body scrolling
            $('body').css('overflow', 'hidden');
          },

          // Close all modals
          closeModal: function () {
            // Only proceed if we found elements
            if (!this.elements.wrapper.length || !this.elements.modals.length) {
              return;
            }

            // Slide out all modals
            this.elements.modals.css(
              'transform',
              `translateX(${this.config.translateValue})`
            );

            // Hide wrapper after animation completes
            setTimeout(() => {
              this.elements.wrapper.addClass(this.config.activeClass);
              $('body').css('overflow', '');
            }, this.config.transitionDuration);
          },

          // Get index of card from trigger
          getCardIndex: function (trigger) {
            if (trigger.closest('.team_card').length) {
              return this.elements.cards.index(trigger.closest('.team_card'));
            }
            return 0;
          },

          // Event handlers
          handleOpenClick: function (e) {
            const cardIndex = this.getCardIndex($(e.currentTarget));
            this.openModal(cardIndex);
            e.preventDefault();
            e.stopPropagation();
          },

          handleCloseClick: function (e) {
            this.closeModal();
            e.preventDefault();
          },

          handleKeyup: function (e) {
            if (e.key === 'Escape') {
              this.closeModal();
            }
          },

          handleWebflowInteraction: function (e) {
            const target = $(e.target);
            if (target.closest('[data-modal="open"]').length) {
              const cardIndex = this.getCardIndex(target);
              this.openModal(cardIndex);
            }
          },

          handleCardClick: function (e) {
            const $this = $(e.currentTarget);
            if (
              $this.find('[data-modal="open"]').length ||
              $this.is('[data-modal="open"]')
            ) {
              const cardIndex = this.getCardIndex($this);
              this.openModal(cardIndex);
              e.preventDefault();
            }
          },

          // Re-initialize when content updates
          reInitialize: function () {
            this.cacheElements();
            this.setupInitialState();
          },
        };

        // Initialize when document is ready
        $(window).on('load', function () {
          ModalController.init();
        });
      })(jQuery);
    </script>

Let’s Talk About

Your Web Journey

Hit the button to let me know what you have in mind, and I will be happy to advise you on how we can move forward together to reach all your goals.