<div class="modal-wrapper modal-wrapper--reserve-in-store js-modal" id="reserve-in-store">
    <div class="modal-overlay js-modal-overlay"></div>
    <div class="modal modal--reserve-in-store">
        <div class="modal__inner">
            <button class="modal__close js-modal-close-button">
        <svg class="icon icon--close-large">
  <use xlink:href="/assets/icons/icons.svg#close-large"></use>
</svg>

      </button>
            <div class="modal__header modal__header--product">
                <span class="modal__title">Reserve in Store</span>
                <span class="modal__sub-title">Product information updated daily</span>
            </div>
            <div class="modal__inner-overlay modal__inner-overlay--white js-modal__inner-overlay js-hidden"><svg class="icon icon--spinner">
  <use xlink:href="/assets/icons/icons.svg#spinner"></use>
</svg>

            </div>
            <div class="modal__content modal__content--product">
                <form class="modal-form modal-form--reserve-in-store js-modal-form" action="8f6ce88d42dd6b994dd53f53149d089a">
                    <div class="modal-form__items">
                        <div class="modal-form__item-group modal-form__item-group--product">
                            <div class="card js-card card--reserve-in-store">
                                <div class="card__inner">
                                    <a class="card__link js-card-url" href="#202-02" data-202-02-url="#202-02" data-B202-2M-url="#B202-2M" data-H202-10-url="#H202-10" data-H202-2M-url="#H202-2M" data-H202-70-url="#H202-70" data-HT202-71-url="#HT202-71" data-H202-2M-2-url="#H202-2M-2" data-H202-70-2-url="#H202-70-2"
                                        data-HT202-71-2-url="#HT202-71-2" data-202-02-stock="true" data-B202-2M-stock="true" data-H202-10-stock="true" data-H202-2M-stock="true" data-H202-70-stock="true" data-HT202-71-stock="true" data-H202-2M-2-stock="true"
                                        data-H202-70-2-stock="true" data-HT202-71-2-stock="true">
      <img class="card__image js-card-image" data-angle="front"
             src="https://mauijim.scene7.com/is/image/mauijim/202-02_front?$config1800$&amp;wid&#x3D;340" data-variant="202-02"
             data-202-02-front="https://mauijim.scene7.com/is/image/mauijim/202-02_front?$config1800$&amp;wid&#x3D;340" data-202-02-angle="https://mauijim.scene7.com/is/image/mauijim/202-02_quarter?$config1800$&amp;wid&#x3D;340" data-202-02-side="https://mauijim.scene7.com/is/image/mauijim/202-02_side?$config1800$&amp;wid&#x3D;340"
                      
             data-B202-2M-front="https://mauijim.scene7.com/is/image/mauijim/B202-2M_front?$config1800$&amp;wid&#x3D;340" data-B202-2M-angle="https://mauijim.scene7.com/is/image/mauijim/B202-2M_quarter?$config1800$&amp;wid&#x3D;340" data-B202-2M-side="https://mauijim.scene7.com/is/image/mauijim/B202-2M_side?$config1800$&amp;wid&#x3D;340"
                      
             data-H202-10-front="https://mauijim.scene7.com/is/image/mauijim/H202-10_front?$config1800$&amp;wid&#x3D;340" data-H202-10-angle="https://mauijim.scene7.com/is/image/mauijim/H202-10_quarter?$config1800$&amp;wid&#x3D;340" data-H202-10-side="https://mauijim.scene7.com/is/image/mauijim/H202-10_side?$config1800$&amp;wid&#x3D;340"
                      
             data-H202-2M-front="https://mauijim.scene7.com/is/image/mauijim/H202-2M_front?$config1800$&amp;wid&#x3D;340" data-H202-2M-angle="https://mauijim.scene7.com/is/image/mauijim/H202-2M_quarter?$config1800$&amp;wid&#x3D;340" data-H202-2M-side="https://mauijim.scene7.com/is/image/mauijim/H202-2M_side?$config1800$&amp;wid&#x3D;340"
                      
             data-H202-70-front="https://mauijim.scene7.com/is/image/mauijim/H202-70_front?$config1800$&amp;wid&#x3D;340" data-H202-70-angle="https://mauijim.scene7.com/is/image/mauijim/H202-70_quarter?$config1800$&amp;wid&#x3D;340" data-H202-70-side="https://mauijim.scene7.com/is/image/mauijim/H202-70_side?$config1800$&amp;wid&#x3D;340"
                      
             data-HT202-71-front="https://mauijim.scene7.com/is/image/mauijim/HT202-71_front?$config1800$&amp;wid&#x3D;340" data-HT202-71-angle="https://mauijim.scene7.com/is/image/mauijim/HT202-71_quarter?$config1800$&amp;wid&#x3D;340" data-HT202-71-side="https://mauijim.scene7.com/is/image/mauijim/HT202-71_side?$config1800$&amp;wid&#x3D;340"
                      
             data-H202-2M-2-front="https://mauijim.scene7.com/is/image/mauijim/H202-2M_front?$config1800$&amp;wid&#x3D;340" data-H202-2M-2-angle="https://mauijim.scene7.com/is/image/mauijim/H202-2M_quarter?$config1800$&amp;wid&#x3D;340" data-H202-2M-2-side="https://mauijim.scene7.com/is/image/mauijim/H202-2M_side?$config1800$&amp;wid&#x3D;340"
                      
             data-H202-70-2-front="https://mauijim.scene7.com/is/image/mauijim/H202-70_front?$config1800$&amp;wid&#x3D;340" data-H202-70-2-angle="https://mauijim.scene7.com/is/image/mauijim/H202-70_quarter?$config1800$&amp;wid&#x3D;340" data-H202-70-2-side="https://mauijim.scene7.com/is/image/mauijim/H202-70_side?$config1800$&amp;wid&#x3D;340"
                      
             data-HT202-71-2-front="https://mauijim.scene7.com/is/image/mauijim/HT202-71_front?$config1800$&amp;wid&#x3D;340" data-HT202-71-2-angle="https://mauijim.scene7.com/is/image/mauijim/HT202-71_quarter?$config1800$&amp;wid&#x3D;340" data-HT202-71-2-side="https://mauijim.scene7.com/is/image/mauijim/HT202-71_side?$config1800$&amp;wid&#x3D;340"
          >
      <h5 class="card__title">PEAHI</h5>
      <span class="card__price js-card-price" data-202-02-price="$149.00" data-B202-2M-price="$189.00" data-H202-10-price="$229.00" data-H202-2M-price="$229.00" data-H202-70-price="$229.00" data-HT202-71-price="$229.00" data-H202-2M-2-price="$229.00" data-H202-70-2-price="$229.00" data-HT202-71-2-price="$229.00">
        $149.00
      </span>
      <span class="card__back-link"><svg class="icon icon--arrow-left">
  <use xlink:href="/assets/icons/icons.svg#arrow-left"></use>
</svg>
 Back</span>
      <span class="card__variant-name js-card-variant-name" data-202-02-variant-name="Gloss Black" data-B202-2M-variant-name="Matte Black" data-H202-10-variant-name="Dark Tortoise" data-H202-2M-variant-name="Matte Black" data-H202-70-variant-name="Redfish" data-HT202-71-variant-name="MahiMahi" data-H202-2M-2-variant-name="Matte Black" data-H202-70-2-variant-name="Redfish" data-HT202-71-2-variant-name="MahiMahi">
        Gloss Black
      </span>
      <svg class="icon icon--arrow-right">
  <use xlink:href="/assets/icons/icons.svg#arrow-right"></use>
</svg>

    </a>
                                    <div class="card__variants-wrapper">
                                        <ul class="card__variants js-card-variants">
                                            <li class="card__variant js-card-variant js-card-variant--active" data-id="202-02">
                                                <button class="card__variant-button js-card-variant-button" style="background-color:#000;" type="button">Gloss Black</button>
                                            </li>
                                            <li class="card__variant js-card-variant" data-id="B202-2M">
                                                <button class="card__variant-button js-card-variant-button" style="background-color:#000;" type="button">Matte Black</button>
                                            </li>
                                            <li class="card__variant js-card-variant" data-id="H202-10">
                                                <button class="card__variant-button js-card-variant-button" style="background-color:#303032;background-image:url(https://mauijim.scene7.com/is/image/mauijim/10);" type="button">Dark Tortoise</button>
                                            </li>
                                            <li class="card__variant js-card-variant" data-id="H202-2M">
                                                <button class="card__variant-button js-card-variant-button" style="background-color:#000;" type="button">Matte Black</button>
                                            </li>
                                            <li class="card__variant js-card-variant" data-id="H202-70">
                                                <button class="card__variant-button js-card-variant-button" style="background-color:#7d4a07;" type="button">Redfish</button>
                                            </li>
                                            <li class="card__variant js-card-variant" data-id="HT202-71">
                                                <button class="card__variant-button js-card-variant-button" style="background-color:#218b16;" type="button">MahiMahi</button>
                                            </li>
                                            <li class="card__variant js-card-variant" data-id="H202-2M-2">
                                                <button class="card__variant-button js-card-variant-button" style="background-color:#000;" type="button">Matte Black</button>
                                            </li>
                                            <li class="card__variant js-card-variant" data-id="H202-70-2">
                                                <button class="card__variant-button js-card-variant-button" style="background-color:#7d4a07;" type="button">Redfish</button>
                                            </li>
                                            <li class="card__variant js-card-variant" data-id="HT202-71-2">
                                                <button class="card__variant-button js-card-variant-button" style="background-color:#218b16;" type="button">MahiMahi</button>
                                            </li>
                                        </ul>
                                        <div class="card__variants-controls js-card-variants-controls">
                                            <button class="card__variants-control card__variants-control--prev" type="button">
          <span class="u-visually-hidden">Previous</span>
          <svg class="icon icon--arrow-left">
  <use xlink:href="/assets/icons/icons.svg#arrow-left"></use>
</svg>

        </button>
                                            <button class="card__variants-control card__variants-control--next" type="button">
          <span class="u-visually-hidden">Next</span>
          <svg class="icon icon--arrow-right">
  <use xlink:href="/assets/icons/icons.svg#arrow-right"></use>
</svg>

        </button>
                                        </div>
                                    </div>
                                </div>
                            </div>

                        </div>
                        <div class="modal-form__item-group modal-form__item-group--views">
                            <div class="views-wrapper js-views-wrapper views-wrapper--default modal-form--views" id="modal-form--views">
                                <div class="view js-view js-view--active view--active js-view--default modal-form--search" id="modal-form--search">
                                    <div class="form-item form-item--zip-geolocate zip-geolocate js-zip-geolocate">

                                        <input value="" class="input zip-geolocate__input js-input-zip-geolocate" type="text" placeholder="Zip code" id="form-example-zip-geolocate" />
                                        <button class="button button--primary zip-geolocate--zip zip-geolocate__button" type="button">
    <svg class="icon icon--search">
  <use xlink:href="/assets/icons/icons.svg#search"></use>
</svg>

    <span class="zip-geolocate__submit-label zip-geolocate__submit-label--large">Find Stores</span>
  </button>
                                        <button class="button button--plain-text zip-geolocate--reset zip-geolocate__button" type="reset">
    <svg class="icon icon--close-large">
  <use xlink:href="/assets/icons/icons.svg#close-large"></use>
</svg>

    <span class="zip-geolocate__submit-label zip-geolocate__submit-label--large u-visually-hidden">Clear</span>
  </button>
                                    </div>

                                    <div class="views-wrapper js-views-wrapper views-wrapper--default modal-form--search-views" id="modal-form--search-views">
                                        <div class="view js-view js-view--active view--active js-view--default modal-form--search-view search-views--start" id="modal-form--search-views--start">
                                            <p class="paragraph reserve-in-store__search-message">Type your Zip code to find stores and see product availability.</p>

                                            <img src="/assets/images/mauijim-brand-logo.png" alt="" class="image reserve-in-store__search-image">

                                        </div>
                                        <div class="view js-view view--hidden modal-form__item-group--error modal-form--search-view search-views--no-results" id="modal-form--search-views--no-results">
                                            <img src="/assets/images/mauijim-brand-mark-grey-small.png" alt="" class="image reserve-in-store__error-image">

                                            <p class="paragraph reserve-in-store__kaumaha">Kaumaha!</p>

                                            <p class="paragraph reserve-in-store__no-results-message">Unfortunately this style is not available to reserve online in your area.</p>

                                        </div>
                                        <div class="view js-view view--hidden modal-form__item-group--error modal-form--search-view search-views--error" id="modal-form--search-views--error">
                                            <img src="/assets/images/mauijim-brand-mark-grey-small.png" alt="" class="image reserve-in-store__error-image">

                                            <p class="paragraph reserve-in-store__kaumaha">Kaumaha!</p>

                                            <p class="paragraph reserve-in-store__error">Something went wrong, please try again later.</p>

                                            <button class="button button--outlined reserve-in-store__continue-shopping" type="button">Continue Shopping</button>

                                        </div>
                                        <div class="view js-view view--hidden modal-form--search-view search-views--store-results" id="modal-form--search-views--store-results">
                                            <div class="zip-geolocate__results reserve-in-store--store-results">
                                                <p class="paragraph reserve-in-store__results-found">
                                                    <span class="reserve-in-store__results-found--results"></span> results for ZIP code <span class="reserve-in-store__results-found--zip"></span>
                                                </p>
                                            </div>

                                            <p class="paragraph reserve-in-store__availability-update">Product availability daily updated.</p>

                                        </div>
                                    </div>

                                </div>
                                <div class="view js-view view--hidden modal-form--form" id="modal-form--form">
                                    <div class="modal-form__item-group--store-info" id="store-info">
                                        <div class="zip-geolocate__results">
                                            <div class="zip-geolocate__result">
                                                <span class="zip-geolocate-result__back-link">
      <svg class="icon icon--arrow-left">
  <use xlink:href="/assets/icons/icons.svg#arrow-left"></use>
</svg>

      Back
    </span>
                                                <div class="zip-geolocate-result__summary zip-geolocate-result__details">
                                                    <span class="zip-geolocate-result__name"></span>
                                                    <span class="zip-geolocate-result__distance"></span>
                                                </div>
                                                <span class="zip-geolocate-result__address zip-geolocate-result__details"></span>
                                                <span class="zip-geolocate-result__type zip-geolocate-result__details">Prescription Retailer</span>
                                                <a href="#" class="zip-geolocate-result__details-link">
      <svg class="icon icon--arrow-right">
  <use xlink:href="/assets/icons/icons.svg#arrow-right"></use>
</svg>

    </a>
                                                <div class="zip-geolocate__actions">
                                                </div>
                                            </div>
                                        </div>

                                        <button class="button button--outlined reserve-in-store--change-store-button" type="button">Change Store</button>

                                    </div>
                                    <div class="modal-form__item-group--contact-info" id="contact-info">
                                        <div class="block block--store-info-contact">
                                            <h3 class="block__heading">Your contact information</h3>
                                            <div class="block__contents">
                                                <p class="paragraph">Please wait for the confirmation email. Email will be sent within 24h.</p>

                                            </div>
                                        </div>

                                    </div>
                                    <div class="modal-form__item-group--contact-info-form" id="contact-info-form">
                                        <div class="form-item form-item--text form-item--reserve-first-name form-item--required">
                                            <label for="reserve-first-name" class="label label--text label--required">First Name</label>
                                            <input type="text" id="reserve-first-name" name="reserve-first-name" class="input input--text">
                                        </div>

                                        <div class="form-item form-item--text form-item--reserve-last-name form-item--required">
                                            <label for="reserve-last-name" class="label label--text label--required">Last Name</label>
                                            <input type="text" id="reserve-last-name" name="reserve-last-name" class="input input--text">
                                        </div>

                                        <div class="form-item form-item--text form-item--reserve-phone-number form-item--required">
                                            <label for="reserve-phone-number" class="label label--text label--required">Phone number</label>
                                            <input type="text" id="reserve-phone-number" name="reserve-phone-number" class="input input--text">
                                        </div>

                                        <div class="form-item form-item--email form-item--reserve-email-address form-item--required">
                                            <label for="reserve-email-address" class="label label--email label--required">Email address</label>
                                            <input type="email" id="reserve-email-address" name="reserve-email-address" class="input input--email">
                                        </div>

                                        <div class="form-item form-item--checkbox">
                                            <input type="checkbox" id="reserve-receive-updates" name="reserve-receive-updates" class="checkbox checkbox--default" checked="true">
                                            <label for="reserve-receive-updates">
    I want to receive email updates and information.
    
  </label>
                                        </div>

                                    </div>
                                    <div class="modal-form__actions js-modal-form-actions">
                                        <div class="modal-form__action">
                                            <button class="button button--primary reserve-variation--button" formnovalidate type="button">Reserve</button>

                                        </div>
                                    </div>
                                    <div class="modal-form__item-group--reservation-info" id="reservation-info">
                                        <p class="paragraph paragraph--store-info-reservation"><strong>Please Note:</strong> You can reserve 5 items daily. After we confirm an item is available, we hold it until the store closes the next day.</p>

                                    </div>
                                </div>
                                <div class="view js-view view--hidden modal-form--form modal-form__item-group--error" id="modal-form--error">
                                    <img src="/assets/images/mauijim-brand-mark-grey-small.png" alt="" class="image reserve-in-store__error-image">

                                    <p class="paragraph reserve-in-store__kaumaha">Kaumaha!</p>

                                    <p class="paragraph reserve-in-store__error">Something went wrong, please try again later or contact the Customer Service at 888-666-5905</p>

                                    <p class="paragraph reserve-in-store__add-to-cart"><a href="#">Add this product to cart</a></p>

                                    <button class="button button--outlined reserve-in-store__continue-shopping" type="button">Continue Shopping</button>

                                </div>
                                <div class="view js-view view--hidden modal-form--confirmation" id="modal-form--confirmation">
                                    <div class="modal-form__item-group--request-received">
                                        <div class="block block--request-received">
                                            <h3 class="block__heading reserve-in-store--request-received--customer-name">Thanks {{reserve--first-name}} {{reserve--last-name}}!</h3>
                                            <div class="block__contents">
                                                <p class="paragraph paragraph--request-received">Your request is received.</p>

                                            </div>
                                        </div>

                                        <div class="block block--request-store-confirmation">
                                            <h3 class="block__heading">Almost Done!</h3>
                                            <div class="block__contents">
                                                <div class="icon-step icon-step--we-contact-you">
                                                    <svg class="icon icon--clock">
  <use xlink:href="/assets/icons/icons.svg#clock"></use>
</svg>

                                                    <span class="icon-step__details"><strong>We'll contact you within 24h</strong> to confirm that your item is ready.</span>
                                                </div>

                                                <div class="icon-step icon-step--check-your-email">
                                                    <svg class="icon icon--action-mail">
  <use xlink:href="/assets/icons/icons.svg#action-mail"></use>
</svg>

                                                    <span class="icon-step__details"><strong>Check your email</strong> {{reserve--email-address}} for further instructions.</span>
                                                </div>

                                                <div class="icon-step icon-step--after-confirmation">
                                                    <svg class="icon icon--store">
  <use xlink:href="/assets/icons/icons.svg#store"></use>
</svg>

                                                    <span class="icon-step__details"><strong>After the confirmation email,</strong> go to the store within the next two days.</span>
                                                </div>

                                            </div>
                                        </div>

                                        <div class="block block--request-store-details">
                                            <h3 class="block__heading">Store Details:</h3>
                                            <div class="block__contents">
                                                <div class="zip-geolocate__results">
                                                    <div class="zip-geolocate__result">
                                                        <div class="zip-geolocate-result__summary zip-geolocate-result__details">
                                                            <span class="zip-geolocate-result__name"></span>
                                                            <span class="zip-geolocate-result__distance"></span>
                                                        </div>
                                                        <span class="zip-geolocate-result__address zip-geolocate-result__details"></span>
                                                        <span class="zip-geolocate-result__type zip-geolocate-result__details">Prescription Retailer</span>
                                                        <div class="zip-geolocate__actions">
                                                        </div>
                                                    </div>
                                                </div>

                                            </div>
                                        </div>

                                        <img src="/assets/images/mauijim-brand-logo.png" alt="" class="image reserved-product__image">

                                        <button class="button button--primary reserved-product__continue-shopping" type="button">Continue Shopping</button>

                                        <p class="paragraph paragraph--store-info-reservation"><strong>Please Note:</strong> You can reserve 5 items daily. After we confirm an item is available, we hold it until the store closes the next day.</p>

                                    </div>
                                </div>
                            </div>

                        </div>
                    </div>
                </form>

            </div>
        </div>
    </div>
</div>
<div class="modal-wrapper modal-wrapper--reserve-in-store js-modal" id="{{id}}">
  <div class="modal-overlay js-modal-overlay"></div>
  <div class="modal modal--{{id}}{{#unless (equals id form)}} modal--{{form}}{{/unless}}">
    <div class="modal__inner">
      <button class="modal__close js-modal-close-button">
        {{render '@icons--close-large'}}
      </button>
      <div class="modal__header{{#if product}} modal__header--product{{/if}}">
        <span class="modal__title">{{title}}</span>
        <span class="modal__sub-title">{{subtitle}}</span>
      </div>
      <div class="modal__inner-overlay modal__inner-overlay--white js-modal__inner-overlay js-hidden">{{render '@spinner'}}</div>
      <div class="modal__content{{#if product}} modal__content--product{{/if}}">
        {{#if description}}
        <p class="modal__description">{{description}}</p>
        {{/if}}
        {{render (dynamicVariant 'modal-form' form) formContext merge=true}}
      </div>
    </div>
  </div>
</div>
{
  "modal": true,
  "id": "reserve-in-store",
  "title": "Reserve in Store",
  "subtitle": "Product information updated daily",
  "product": true,
  "form": "reserve-in-store",
  "formContext": {
    "columns": null
  }
}
  • Content:
    (function (window) {
      'use strict';
    
      const modalForm = document.querySelector('.modal--reserve-in-store');
      const storeDetailsLink = document.querySelector('.zip-geolocate-result__details-link');
      const storeBackLink = document.querySelector('.zip-geolocate-result__back-link');
    
      const modalCard = document.querySelector('.card--reserve-in-store');
      const modalCardClass = 'js-card-reserve-in-store--detail';
    
      const modalInnerOverlay = document.querySelector('.modal-wrapper--reserve-in-store .js-modal__inner-overlay');
    
      const buttonZipGeolocate = document.querySelector('.zip-geolocate--zip');
      const inputZipGeolocate = document.querySelector('.zip-geolocate__input');
    
      const startView = document.querySelector('#modal-form--search-views--start');
      const noResultsView = document.querySelector('#modal-form--search-views--no-results');
      const storeResultsView = document.querySelector('#modal-form--search-views--store-results');
      const searchErrorView = document.querySelector('#modal-form--search-views--error');
    
      const searchView = document.querySelector('#modal-form--search');
      const formView = document.querySelector('#modal-form--form');
      const confirmationView = document.querySelector('#modal-form--confirmation');
      const errorView = document.querySelector('#modal-form--error');
    
      const storeResults = document.querySelector('.reserve-in-store--store-results');
      const changeStoreButton = document.querySelector('.reserve-in-store--change-store-button');
      const reserveButton = document.querySelector('.reserve-variation--button');
    
      const card = document.querySelector('.card--reserve-in-store');
      let variants = null;
    
      if(card !== null) {
        variants = card.querySelectorAll('.js-card-variant');
      }
    
      function toggleStoreDetail(e) {
        modalForm.classList.toggle('js-form-store-info');
    
        if(modalForm.classList.contains('js-form-store-info')) {
          changeStoreButton.addEventListener('click', toggleStoreDetail);
        } else {
          changeStoreButton.removeEventListener('click', toggleStoreDetail);
        }
    
        e.preventDefault();
      }
    
      function toggleCardDetail(e) {
        const modalCardParent = document.querySelector('.js-card.card--reserve-in-store').closest('.modal--reserve-in-store');
    
        if (modalCardParent) {
          modalCardParent.classList.toggle(modalCardClass);
    
          for(let i = 0; i < variants.length; i++) {
            if(modalCardParent.classList.contains(modalCardClass)) {
              variants[i].addEventListener('click', toggleCardDetail);
            } else {
              variants[i].removeEventListener('click', toggleCardDetail);
            }
          }
        }
    
        e.preventDefault();
      }
    
      function toggleInnerOverlay(e) {
        const modalInnerOverlaySpinner = modalInnerOverlay.querySelector('.icon--spinner');
    
        // Toggle spinner icon, overlay and event listeners for toggling visibility
        if(e.type === 'hideOverlay') {
          if(modalInnerOverlaySpinner) {
            const svgClass = modalInnerOverlaySpinner.getAttribute('class').replace(/js-show/, '');
            modalInnerOverlaySpinner.setAttribute('class', svgClass);
          }
          modalInnerOverlay.classList.add('js-hidden');
          modalInnerOverlay.addEventListener('showOverlay', toggleInnerOverlay, {once: true});
        } else {
          if(modalInnerOverlaySpinner) {
            const svgClass = modalInnerOverlaySpinner.getAttribute('class') + ' js-show';
            modalInnerOverlaySpinner.setAttribute('class', svgClass);
          }
          modalInnerOverlay.classList.remove('js-hidden');
          modalInnerOverlay.addEventListener('hideOverlay', toggleInnerOverlay, {once: true});
        }
      }
    
      function showInnerOverlay() {
        modalInnerOverlay.dispatchEvent(new CustomEvent('showOverlay'));
      }
    
      function hideInnerOverlay() {
        modalInnerOverlay.dispatchEvent(new CustomEvent('hideOverlay'));
      }
    
      function activateView(view, callback = handleViewActivated) {
        view.addEventListener('viewActivated', callback, {once: true});
        view.dispatchEvent(new CustomEvent('activateView'));
      }
    
      function handleViewActivated(e) {
        hideInnerOverlay();
      }
    
      function changeStore(e) {
        showInnerOverlay();
    
        card.dispatchEvent(new CustomEvent('deselectVariant'));
    
        activateView(searchView);
      }
    
      function updateStoreDetails(storeName, storeDistance, storeAddress, storePrescription) {
        formView.querySelector('.zip-geolocate-result__name').textContent = storeName;
        formView.querySelector('.zip-geolocate-result__distance').textContent = storeDistance;
        formView.querySelector('.zip-geolocate-result__address').textContent = storeAddress;
    
        if(storePrescription) {
          formView.querySelector('.zip-geolocate-result__type').classList.remove('js-hidden');
        } else {
          formView.querySelector('.zip-geolocate-result__type').classList.add('js-hidden');
        }
    
        confirmationView.querySelector('.zip-geolocate-result__name').textContent = storeName;
        confirmationView.querySelector('.zip-geolocate-result__distance').textContent = storeDistance;
        confirmationView.querySelector('.zip-geolocate-result__address').textContent = storeAddress;
    
        if(storePrescription) {
          confirmationView.querySelector('.zip-geolocate-result__type').classList.remove('js-hidden');
        } else {
          confirmationView.querySelector('.zip-geolocate-result__type').classList.add('js-hidden');
        }
      }
    
      function selectStore(e) {
        showInnerOverlay();
    
        const store = e.target.closest('.zip-geolocate__result');
        const storeName = store.getAttribute('data-store-name');
        const storeDistance = store.getAttribute('data-store-distance');
        const storeAddress = store.getAttribute('data-store-address');
        const storePrescription = store.getAttribute('data-store-prescription') === "true"  ;
    
        // Store the selected location details on the tradeAppApi object
        window.tradeAppApi.locationId = parseInt(store.getAttribute('data-store-id'));
        window.tradeAppApi.locationName = store.getAttribute('data-store-name');
        window.tradeAppApi.locationAddress = store.getAttribute('data-store-address');
        updateStoreDetails(storeName, storeDistance, storeAddress, storePrescription);
    
        card.dispatchEvent(new CustomEvent('selectVariant'));
    
        activateView(formView);
    
        e.preventDefault();
      }
    
      function setSearchResultsSummary(resultsNum, zipCode) {
        storeResultsView.querySelector('.reserve-in-store__results-found--results').textContent = resultsNum + "";
        storeResultsView.querySelector('.reserve-in-store__results-found--zip').textContent = zipCode;
      }
    
      function emptyResultsContainer() {
        while (storeResults.querySelector('.zip-geolocate__result')) {
          storeResults.removeChild(storeResults.querySelector('.zip-geolocate__result'));
        }
      }
    
      function createResultContainer(store) {
        const result = document.createElement('div');
    
        // Add zip-geolocate__result class
        result.classList.add('zip-geolocate__result');
    
        // Set result attributes
        result.setAttribute('data-store-id', store.locationId);
        result.setAttribute('data-store-name', store.name);
        result.setAttribute('data-store-distance', store.distance);
        result.setAttribute('data-store-distance-unit', store.distanceUnit);
        result.setAttribute('data-store-address', store.address);
        result.setAttribute('data-store-latitude', store.hasOwnProperty('geoLocation') && store.geoLocation.hasOwnProperty('coordinates') ? store.geoLocation.coordinates[0] : null);
        result.setAttribute('data-store-longitude', store.hasOwnProperty('geoLocation') && store.geoLocation.hasOwnProperty('coordinates') ? store.geoLocation.coordinates[1] : null);
        result.setAttribute('data-store-postcode', store.hasOwnProperty('zipCode') ? store.zipCode : null);
        result.setAttribute('data-store-prescription', store.hasOwnProperty('prescriptionRetailer') ? store.prescriptionRetailer : false);
    
        // Append result summary
        result.appendChild(createResultSummary(store.name, store.distance, store.distanceUnit));
    
        // Append result address
        result.appendChild(createResultAddress(store.address));
    
        // Append result prescription label
        if(store.hasOwnProperty('prescriptionRetailer') && store.prescriptionRetailer) {
          result.appendChild(createResultPrescriptionLabel(window.ris_i18n.prescription_retailer));
        }
    
        // Append result actions
        result.appendChild(createResultActions(window.ris_i18n.reserve_now));
    
        return result;
      }
    
      function createResultSummary(storeName, storeDistance, distanceUnit) {
        const summary = document.createElement('div');
        summary.classList.add('zip-geolocate-result__summary');
        summary.classList.add('zip-geolocate-result__details');
    
        // Append store name
        summary.appendChild(createResultName(storeName));
    
        // Append store distance
        summary.appendChild(createResultDistance(storeDistance, distanceUnit));
    
        return summary;
      }
    
      function createResultName(storeName) {
        const name = document.createElement('span');
    
        name.classList.add('zip-geolocate-result__name');
        name.textContent = storeName;
        return name
      }
    
      function createResultDistance(storeDistance, distanceUnit) {
        const distance = document.createElement('span');
    
        distance.classList.add('zip-geolocate-result__distance');
        distance.textContent = `${storeDistance} ${distanceUnit}`;
    
        return distance;
      }
    
      function createResultAddress(storeAddress) {
        const address = document.createElement('span');
    
        address.classList.add('zip-geolocate-result__address');
        address.classList.add('zip-geolocate-result__details');;
        address.textContent = storeAddress;
    
        return address;
      }
    
      function createResultPrescriptionLabel(prescriptionLabel) {
        const prescription = document.createElement('span');
    
        prescription.classList.add('zip-geolocate-result__type');
        prescription.classList.add('zip-geolocate-result__details');;
        prescription.textContent = prescriptionLabel;
    
        return prescription;
      }
    
      function createResultActions(reserveText) {
        const actions = document.createElement('div');
    
        actions.classList.add('zip-geolocate__actions');
        actions.appendChild(createResultAction(reserveText));
    
        return actions;
      }
    
      function createResultAction(reserveText) {
        const reserve = document.createElement('button');
    
        // Generate store "reserve now" action
        reserve.classList.add('button');
        reserve.classList.add('button--primary');
        reserve.classList.add('zip-geolocate__action');
        reserve.classList.add('zip-geolocate__action-reserve');
        reserve.setAttribute('type', 'button');
        reserve.textContent = reserveText;
    
        reserve.addEventListener('click', selectStore);
    
        return reserve;
      }
    
      function populateStoreResults(response) {
        if(response.data.length === 0) { // If no results are available
          // Activate no-results view
          activateView(noResultsView);
        } else { // Otherwise
          // Populate search recap notice
          setSearchResultsSummary(response.data.length, window.tradeAppApi.zipCode);
    
          // Empty results container
          emptyResultsContainer();
    
          // Populate results container
          for (let i = 0; i < response.data.length; i++) {
            storeResults.appendChild(createResultContainer(response.data[i]));
          }
    
          // Activate store results view
          activateView(storeResultsView);
        }
      }
    
      function handleStoreListRequest(e) {
        showInnerOverlay();
    
        window.tradeAppApi.sku = document.querySelector('.card--reserve-in-store .js-card-variant--active').getAttribute('data-id');
        window.tradeAppApi.zipCode = e.detail.zip;
    
        if(window.tradeAppApi._demo === false) {
          let selectedVariant = null;
          for(let i = 0; i < window.tradeAppApiConfig.product.variants.length; i++) {
            if(window.tradeAppApiConfig.product.variants[i].sku === window.tradeAppApi.sku) {
              selectedVariant = window.tradeAppApiConfig.product.variants[i];
              break;
            }
          }
          window.tradeAppApi.variation = {
            category: window.tradeAppApiConfig.product.category,
            style: window.tradeAppApiConfig.product.style,
            frame: selectedVariant.frame,
            lens: selectedVariant.lens,
            image: selectedVariant.image,
            url: window.tradeAppApiConfig.product.url
          };
        }
    
        window.tradeAppApi.getLocations(populateStoreResults, handleSearchError);
      }
    
      function handleVariantSwitch(e) {
        buttonZipGeolocate.click();
      }
    
      function activateVariantSwitch(e) {
        for(let i = 0; i < variants.length; i++) {
          variants[i].addEventListener('click', handleVariantSwitch);
        }
      }
    
      function handleSearchError(response) {
        activateView(searchErrorView);
      }
    
      function deactivateVariantSwitch(e) {
        for(let i = 0; i < variants.length; i++) {
          variants[i].removeEventListener('click', handleVariantSwitch);
        }
      }
    
      function switchToStartView(e) {
        showInnerOverlay();
        activateView(startView);
      }
    
      function setFieldError(input, message) {
        const formItem = input.closest('.form-item');
        let inputError = formItem.querySelector('span.input-error');
    
        if(!inputError) {
          inputError = document.createElement('span');
          inputError.classList.add('input-error');
          inputError.classList.add('js-hidden');
          formItem.appendChild(inputError);
        }
    
        inputError.textContent = message;
        inputError.classList.remove('js-hidden');
        formItem.classList.add('form-item--error');
      }
    
      function unsetFieldError(e) {
        const input = e.currentTarget;
        const formItem = input.closest('.form-item');
        const inputError = formItem.querySelector('span.input-error') || Array.prototype.filter.call(formItem.parentNode.children, el => el.classList.contains('input-error'))[0];
    
        if(inputError) {
          inputError.classList.add('js-hidden');
        }
    
        formItem.classList.remove('form-item--error');
      }
    
      function validateRequiredField(field) {
        if(!field.value || field.value.trim() === "") {
          setFieldError(field, window.ris_i18n.required_field);
          field.addEventListener('input', unsetFieldError, {once: true});
          changeStoreButton.addEventListener('click', () => { unsetFieldError({currentTarget: field}); }, {once: true});
          return false;
        }
    
        return true;
      }
    
      function validatePersonName(field) {
        if(! /^[A-z\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1 \'\+\-\.]{1,100}$/i.test(field.value.trim())) {
          setFieldError(field, window.ris_i18n.invalid_name);
          field.addEventListener('input', unsetFieldError, {once: true});
          changeStoreButton.addEventListener('click', () => { unsetFieldError({currentTarget: field}); }, {once: true});
          return false;
        }
    
        return true;
      }
    
      function validateEmailAddress(field) {
        if(! /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i.test(field.value.trim())) {
          setFieldError(field, window.ris_i18n.invalid_email_address);
          field.addEventListener('input', unsetFieldError, {once: true});
          changeStoreButton.addEventListener('click', () => { unsetFieldError({currentTarget: field}); }, {once: true});
          return false;
        }
    
        return true;
      }
    
      function validatePhoneNumber(field) {
        if(! /^[0-9+ ()-]*$/i.test(field.value.trim())) {
          setFieldError(field, window.ris_i18n.invalid_phone_number);
          field.addEventListener('input', unsetFieldError, {once: true});
          changeStoreButton.addEventListener('click', () => { unsetFieldError({currentTarget: field}); }, {once: true});
          return false;
        }
    
        return true;
      }
    
      function updateConfirmationDetails(firstName, lastName, emailAddress) {
        confirmationView.querySelector('.block--request-received').innerHTML = confirmationView.querySelector('.block--request-received').innerHTML.replace('{{reserve--first-name}}', firstName)
          .replace('{{reserve--last-name}}', lastName);
        confirmationView.querySelector('.block--request-store-confirmation').innerHTML = confirmationView.querySelector('.block--request-store-confirmation').innerHTML.replace('{{reserve--email-address}}', emailAddress);
      }
    
      function resetModalViews(modal) {
        if(modal.action === "close" && modal.id == 'reserve-in-store') {
          const viewsWrappers = document.querySelectorAll(`#${modal.id} .js-views-wrapper`);
          const modalFormForm = modalForm.querySelector('form');
    
          // Reset card
          card.dispatchEvent(new CustomEvent('resetVariant'));
    
          // Reset all views
          for(let i = 0; i < viewsWrappers.length; i++) {
            viewsWrappers[i].dispatchEvent(new CustomEvent('resetView'));
          }
    
          // Reset form
          modalFormForm.dispatchEvent(new CustomEvent('reset'));
    
          // Reset errors
          const inputFields = modalFormForm.querySelectorAll('input');
          for(let i = 0; i < inputFields.length; i++) {
            unsetFieldError({currentTarget: inputFields[i]});
          }
    
          // Reset Placeholders
          const dataContents = modalFormForm.querySelectorAll('[data-content]');
          for(let i = 0; i < dataContents.length; i++) {
            dataContents[i].innerHTML = atob(dataContents[i].getAttribute('data-content'));
          }
    
          // Reset Variant Switcher
          componentEvents.on('modal-change', setInitialVariant);
          modalForm.classList.remove('js-modal--reserve-in-store-initiated');
    
          // Deactivate trigger on variant switching
          deactivateVariantSwitch();
          buttonZipGeolocate.addEventListener('zip', activateVariantSwitch, {once: true});
    
          // Enable initial variant detection
          componentEvents.on('modal-change', setInitialVariant);
        }
      }
    
      function validateReserveForm(e) {
        const reserveFirstName = formView.querySelector('#reserve-first-name');
        const reserveLastName = formView.querySelector('#reserve-last-name');
        const reserveEmailAddress = formView.querySelector('#reserve-email-address');
        const reservePhoneNumber = formView.querySelector('#reserve-phone-number');
        const reserveSubscribe = formView.querySelector('#reserve-receive-updates');
        let valid = true;
    
        valid = validateRequiredField(reserveFirstName) && validatePersonName(reserveFirstName) && valid;
        valid = validateRequiredField(reserveLastName) && validatePersonName(reserveLastName) && valid;
        valid = validateRequiredField(reserveEmailAddress) && validateEmailAddress(reserveEmailAddress) && valid;
        valid = validateRequiredField(reservePhoneNumber) && validatePhoneNumber(reservePhoneNumber) && valid;
    
        if(valid) {
          showInnerOverlay();
    
          window.tradeAppApi.customer = {
            firstName: reserveFirstName.value.trim(),
            lastName: reserveLastName.value.trim(),
            email: reserveEmailAddress.value.trim(),
            phone: reservePhoneNumber.value.trim(),
            subscribe: false || reserveSubscribe.checked
          };
    
          window.tradeAppApi.createOrder(confirmReservation, handleReservationError);
        }
      }
    
      function handleReservationError(response) {
        activateView(errorView);
      }
    
      function confirmReservation(response) {
        updateConfirmationDetails(window.tradeAppApi.customer.firstName, window.tradeAppApi.customer.lastName, window.tradeAppApi.customer.email);
    
        activateView(confirmationView, evt => {
          card.dispatchEvent(new CustomEvent('confirmVariant'));
          handleViewActivated(evt);
        });
      }
    
      function setInitialVariant(modal) {
        if(modal.action === "open" && modal.id === 'reserve-in-store') {
          if (!modalForm.classList.contains('js-modal--reserve-in-store-initiated')) {
            const pdpVariant = document.querySelector('.js-product-detail-variant--active');
            card.querySelector(`.js-card-variant[data-id="${pdpVariant.getAttribute('data-id')}"]`).click();
    
            componentEvents.off('modal-change', setInitialVariant);
            modalForm.classList.add('js-modal--reserve-in-store-initiated');
          }
        }
      }
    
      function init() {
        if (storeDetailsLink) {
          storeDetailsLink.addEventListener('click', toggleStoreDetail);
        }
    
        if (storeBackLink) {
          storeBackLink.addEventListener('click', toggleStoreDetail);
        }
    
        if (modalCard) {
          const cardDetailLink = modalCard.querySelector('.card__link');
    
          cardDetailLink.addEventListener('click', toggleCardDetail);
        }
    
        if(modalInnerOverlay) {
          modalInnerOverlay.addEventListener('showOverlay', toggleInnerOverlay, {once: true});
        }
    
        if(buttonZipGeolocate) {
          buttonZipGeolocate.addEventListener('zip', handleStoreListRequest);
          buttonZipGeolocate.addEventListener('zip', activateVariantSwitch, {once: true});
          buttonZipGeolocate.addEventListener('zip-error', switchToStartView);
        }
    
        if(changeStoreButton) {
          changeStoreButton.addEventListener('click', changeStore);
        }
    
        if(reserveButton) {
          reserveButton.addEventListener('click', validateReserveForm);
        }
    
        componentEvents.on('modal-change', setInitialVariant);
        componentEvents.on('modal-change', resetModalViews);
    
        if(typeof window.ris_i18n === "undefined" || window.ris_i18n === null) {
          window.ris_i18n = {
            "empty_zip_code": "Please enter a Zip code.",
            "invalid_zip_code": "Zip code incorrect. Please verify.",
            "zip_code_regex": /^[0-9]{5}$/,
            "prescription_retailer": "Prescription Retailer",
            "reserve_now": "Reserve Now",
            "required_field": "Required field.",
            "invalid_name": "Invalid name.",
            "invalid_email_address": "Invalid email address.",
            "invalid_phone_number": "Invalid phone number.",
          };
        } else {
          if(!window.ris_i18n.hasOwnProperty('empty_zip_code') || window.ris_i18n.empty_zip_code === '') {
            window.ris_i18n.empty_zip_code = "Please enter a Zip code.";
          }
    
          if(!window.ris_i18n.hasOwnProperty('invalid_zip_code') || window.ris_i18n.invalid_zip_code === '') {
            window.ris_i18n.invalid_zip_code = "Zip code incorrect. Please verify.";
          }
    
          if(!window.ris_i18n.hasOwnProperty('zip_code_regex')) {
            window.ris_i18n.zip_code_regex = /^[0-9]{5}?$/;
          }
    
          if(!window.ris_i18n.hasOwnProperty('prescription_retailer') || window.ris_i18n.prescription_retailer === '') {
            window.ris_i18n.prescription_retailer = "Prescription Retailer";
          }
    
          if(!window.ris_i18n.hasOwnProperty('reserve_now') || window.ris_i18n.reserve_now === '') {
            window.ris_i18n.reserve_now = "Reserve Now";
          }
    
          if(!window.ris_i18n.hasOwnProperty('required_field') || window.ris_i18n.required_field === '') {
            window.ris_i18n.required_field = "Required field.";
          }
    
          if(!window.ris_i18n.hasOwnProperty('invalid_name') || window.ris_i18n.invalid_name === '') {
            window.ris_i18n.invalid_name = "Invalid name.";
          }
    
          if(!window.ris_i18n.hasOwnProperty('invalid_email_address') || window.ris_i18n.invalid_email_address === '') {
            window.ris_i18n.invalid_email_address = "Invalid email address.";
          }
    
          if(!window.ris_i18n.hasOwnProperty('invalid_phone_number') || window.ris_i18n.invalid_phone_number === '') {
            window.ris_i18n.invalid_phone_number = "Invalid phone number.";
          }
        }
      }
    
      init();
    
    })(this);
    
  • URL: /components/raw/reserve-in-store/reserve-in-store.js
  • Filesystem Path: src/components/01-elements/modals/reserve-in-store/reserve-in-store.js
  • Size: 23.2 KB
  • Content:
    .modal--reserve-in-store {
      min-width: 320px;
    }
    
    .js-card-reserve-in-store--detail {
      .modal-form__actions {
        display: none;
      }
    
      .modal__header {
        position: relative;
        box-shadow: 0 0 10px rgba(0, 0, 0, .1);
        z-index: 1;
      }
    }
    
    .modal-wrapper--reserve-in-store {
      -webkit-text-size-adjust: 100%;
    
      .modal__header {
        min-height: 5rem;
        padding-top: 0;
    
        .modal__title {
          margin-bottom: 4px;
          padding-top: 6px;
          line-height: 1.9rem;
          box-shadow: none;
    
          @include breakpoint($breakpoint-md) {
            padding-top: 8px;
          }
    
          @include breakpoint($breakpoint-xl) {
            padding-top: 11px;
            line-height: 2.8rem;
          }
        }
    
        .modal__sub-title {
          display: block;
          color: $color-medium-dark;
          font-size: 1.2rem;
          letter-spacing: 0;
          line-height: 1.7rem;
          text-align: center;
    
    
          @include breakpoint($breakpoint-xl) {
            display: none;
          }
        }
      }
    
      .modal__header--product {
        height: 50px;
        margin-bottom: 10px;
        box-shadow: 0 0 10px 0 rgba(0, 0, 0, .1);
    
        @include breakpoint($breakpoint-xl) {
          margin-bottom: 26px;
          box-shadow: none;
        }
      }
    
      .modal__content--product {
        @include breakpoint($breakpoint-sm-only) {
          overflow-x: hidden;
          overflow-y: hidden;
        }
    
        height: calc(100vh - 70px);
        padding: 0;
    
        @include breakpoint($breakpoint-xl) {
          height: 690px;
        }
      }
    
      .modal-form__items {
        @include breakpoint($breakpoint-md) {
          padding: 0;
        }
      }
    
      .modal-form__item-group--product {
        @include breakpoint($breakpoint-sm-only) {
          width: 100%;
          z-index: 1;
        }
      }
    
      .modal__inner {
        @include breakpoint($breakpoint-md) {
          position: fixed;
          top: 0;
          width: 100%;
          max-width: 100%;
          height: 100%;
        }
    
        @include breakpoint($breakpoint-lg) {
          width: 100%;
          max-width: 100%;
        }
    
        @include breakpoint($breakpoint-xl) {
          position: relative;
          width: calc(100% - 40px);
          max-width: 980px;
          height: 750px;
        }
      }
    
      .modal__inner-overlay {
        display: flex;
        position: absolute;
        align-items: center;
        justify-content: center;
        width: 100%;
        height: calc(100% - 50px);
        background-color: rgba(0, 0, 0, .75);
        z-index: 2;
    
        &.modal__inner-overlay--white {
          background-color: rgba(255, 255, 255, .75);
        }
    
        .icon.icon--spinner {
          margin-top: -25px;
        }
    
        @include breakpoint($breakpoint-md) {
          height: calc(100% - 75px);
    
          .icon.icon--spinner {
            margin-top: -75px;
          }
        }
      }
    
      .modal__close {
        width: 34px;
        height: 50px;
    
        .icon {
          width: 14px;
          height: 14px;
        }
    
        @include breakpoint($breakpoint-md) {
          .icon {
            margin-top: 0;
            margin-right: 0;
          }
        }
    
        @include breakpoint($breakpoint-xl) {
          width: 66px;
    
          .icon {
            width: 16px;
            height: 16px;
            margin-right: 30px;
          }
        }
      }
    }
    
    .js-form-store-info {
      @include breakpoint($breakpoint-sm-only) {
        .modal__header--product {
          box-shadow: 0 0 10px rgba(0, 0, 0, .1);
        }
    
        .zip-geolocate__results {
          margin-bottom: 3px;
        }
    
        .zip-geolocate__result {
          padding: 0;
          border-bottom-style: none;
    
          .zip-geolocate-result__address {
            margin-bottom: 0;
          }
        }
    
        .reserve-in-store--change-store-button {
          width: auto;
          padding-right: 0;
          padding-left: 0;
        }
    
        .card--reserve-in-store,
        .zip-geolocate-result__details-link,
        .modal-form__item-group--contact-info,
        .modal-form__item-group--contact-info-form,
        .modal-form__item-group--reservation-info,
        .modal-form__actions {
          display: none;
        }
    
        .zip-geolocate-result__back-link,
        .modal-form__item-group--store-info .zip-geolocate-result__type,
        .modal-form__item-group--store-info .button--outlined,
        .table {
          display: block;
        }
    
        .table {
          padding-top: 20px;
          border-top: 1px solid $color-light;
        }
      }
    }
    
  • URL: /components/raw/reserve-in-store/reserve-in-store.scss
  • Filesystem Path: src/components/01-elements/modals/reserve-in-store/reserve-in-store.scss
  • Size: 4.1 KB

There are no notes for this item.