Announcement

Collapse
No announcement yet.

Highlight active swatch selection

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Highlight active swatch selection

    Have a client who would like to highlight the active swatch on their product listings, much like the Colossus theme. I see in Colossus, when a swatch is clicked a class is added to the image that highlights the image and allows you to know which one has been checked. When I check a view source on Shadows, there isn't any class added to indicate that the particular image is the active one.

    Everything appears to be the exact same in both themes with regards to classes (o-lisst-inline, o-list-inline__item), except selecting a swatch in Colossus adds the following to the img:
    class="x-product-layout-purchase__swatches--active"

    Any guidance as to how we could duplicate that functionality? I've done some searching and can't seem to find how that might be implemented and am stumped.

    Thanks!

  • The swatch identification function is included in Shadows as well as Colossus; you can see an example of it here: https://shadows.mivareadythemes.com/product-1.html
    Can you post a link to the page in question? Are you receiving any errors on the page?
    Matt Zimmermann
    Director of UI/UX Standards and Theme Development
    / Miva, Inc.

    Comment


    • Circling back around to this
      I've tried to figure out what is missing from the PROD page, but everything to me looks to be ok.
      Here is a link to a particular product:
      https://www.pmlproducts.com/valve-co...-and-fins.html

      clicking on the attributes changes the main picture, but looks like it doesn't add the class "x-product-layout-purchase__swatches--active" to the selected image. Backing up the edits that the client did doesn't magically correct the issue.

      Attribute Head code on the PROD page:

      Code:
      <script>
          AttributeMachine.prototype.Generate_Discount = function (discount) {
              var discount_div;
      
              discount_div = document.createElement('div');
              discount_div.innerHTML = discount.descrip + ': ' + discount.formatted_discount;
      
              return discount_div;
          };
      
          AttributeMachine.prototype.Generate_Swatch = function (product_code, attribute, option) {
              var swatch_container = document.querySelector('#&mvt:attributemachine:swatch_element_id;');
              var swatch = document.createElement('li');
              var img = document.createElement('img');
      
              img.src = option.image;
              img.setAttribute('alt', option.prompt);
              img.setAttribute('title', option.prompt);
              swatch.classList.add('o-list-inline__item');
              swatch.setAttribute('data-code', option.code);
              swatch.setAttribute('data-color', option.prompt);
              swatch.appendChild(img);
      
              setTimeout(function () {
                  if (swatch_container) {
                      var swatch_element = swatch_container.querySelector('ul');
      
                      swatch_element.removeAttribute('style');
                      swatch_element.classList.add('o-list-inline');
                  }
              }, 0);
      
              return swatch;
          };
      
          AttributeMachine.prototype.Swatch_Click = function(input, attribute, option) {
              var i;
              var swatch_name_element = document.querySelector('[data-hook="attribute-swatch-name"]');
      
              for (i = 0; i < input.select.options.length; i++) {
                  if (input.select.options[i].value === option.code) {
                      input.select.selectedIndex = i;
                  }
              }
      
              if (attribute.inventory) {
                  this.Attribute_Changed(input);
              }
      
              swatch_name_element.innerHTML = option.prompt;
          };
      
          window.addEventListener('load', function () {
              var swatch_container = document.querySelector('#&mvt:attributemachine:swatch_element_id;');
      
              if (swatch_container) {
                  var swatch_element = swatch_container.querySelector('ul');
                  var swatch_select = document.querySelector('[data-hook="attribute-swatch-select"]');
                  var swatch_selected = swatch_select.options[swatch_select.selectedIndex].text;
                  var swatch_name_element = document.querySelector('[data-hook="attribute-swatch-name"]');
      
                  swatch_element.removeAttribute('style');
                  swatch_element.classList.add('o-list-inline');
                  swatch_name_element.textContent = swatch_selected;
      
                  swatch_select.addEventListener('change', function () {
                      swatch_name_element.textContent = this.options[this.selectedIndex].text
                  });
              }
          }, false);
      </script>
      Here is the product attribute template code.

      Code:
      <mvt:foreach iterator="attribute" array="attributes">
          <mvt:assign name="l.settings:attribute_ID" value="'l-' $ tolower(l.settings:attribute:code)" />
          <mvt:if expr="l.settings:attribute:required">
              <mvt:assign name="l.settings:required_attribute" value="'required'" />
              <mvt:assign name="l.settings:required_attribute_classes" value="'u-text-bold is-required'" />
          <mvt:else>
              <mvt:assign name="l.settings:required_attribute" value="''" />
              <mvt:assign name="l.settings:required_attribute_classes" value="''" />
          </mvt:if>
          <input data-attribute-type="&mvte:attribute:type;" type="hidden" name="Product_Attributes[&mvte:attribute:index;]:code" value="&mvte:attribute:code;">
          <mvt:if expr="l.settings:attribute:template_code NE 0">
              <input type="hidden" name="Product_Attributes[&mvte:attribute:index;]:template_code" value="&mvte:attribute:template_code;">
          </mvt:if>
          <mvt:if expr="l.settings:attribute:type EQ 'text'">
              <div class="x-product-layout-purchase__options-attribute o-layout__item">
                  <label class="c-form-label &mvt:required_attribute_classes;" for="&mvt:attribute_ID;" title="&mvte:attribute:prompt;">&mvte:attribute:prompt;</label>
                  <input id="&mvt:attribute_ID;" class="c-form-input c-form-input--large" data-attribute="&mvte:attribute:code;" data-option-price="&mvt:attribute:price;" data-regular-price="" type="text" name="Product_Attributes[&mvte:attribute:index;]:value" value="&mvte:attribute:value;" placeholder="" &mvt:required_attribute;>
              </div>
          <mvt:elseif expr="l.settings:attribute:type EQ 'memo'">
              <div class="x-product-layout-purchase__options-attribute o-layout__item">
                  <label class="c-form-label &mvt:required_attribute_classes;" for="&mvt:attribute_ID;" title="&mvte:attribute:prompt;">&mvte:attribute:prompt;</label>
                  <textarea id="&mvt:attribute_ID;" class="c-form-input c-form-input--large c-form-input--long" data-attribute="&mvte:attribute:code;" data-option-price="&mvt:attribute:price;" data-regular-price="" name="Product_Attributes[&mvt:attribute:index;]:value" placeholder="" &mvt:required_attribute;>&mvte:attribute:value;</textarea>
              </div>
          <mvt:elseif expr="l.settings:attribute:type EQ 'radio'">
              <div class="x-product-layout-purchase__options-attribute o-layout__item">
                  <span class="c-form-label u-block &mvt:required_attribute_classes;" title="&mvte:attribute:prompt;">&mvte:attribute:prompt;</span>
                  <mvt:foreach iterator="option" array="attribute:options">
                      <label class="c-form-checkbox c-form-checkbox--radio c-form-checkbox--inline" title="&mvt:option:prompt;">
                          <mvt:if expr="((g.Product_Attributes[l.settings:attribute:index]:value EQ 0) AND (l.settings:option:id EQ l.settings:attribute:default_id)) OR (g.Product_Attributes[l.settings:attribute:index]:value EQ l.settings:option:code)">
                              <input class="c-form-checkbox__input" data-attribute="&mvte:attribute:code;" data-option-price="&mvt:option:price;" data-regular-price="" type="radio" name="Product_Attributes[&mvte:attribute:index;]:value" value="&mvte:option:code;" checked &mvt:required_attribute;>
                          <mvt:else>
                              <input class="c-form-checkbox__input" data-attribute="&mvte:attribute:code;" data-option-price="&mvt:option:price;" data-regular-price="" type="radio" name="Product_Attributes[&mvte:attribute:index;]:value" value="&mvte:option:code;" &mvt:required_attribute;>
                          </mvt:if>
                          <span class="c-form-checkbox__caption">
                              <mvt:if expr="l.settings:option:image">
                                  <img src="&mvte:option:image;" alt="&mvte:option:prompt;" title="&mvte:option:prompt;" />
                              <mvt:else>
                                  &mvte:option:prompt;
                                  <mvt:if expr="l.settings:option:price">
                                      <mvt:if expr="l.settings:option:price GT 0">
                                          &nbsp;<mvt:eval expr="'+ $' $ rnd(l.settings:option:price, 2)" />
                                      <mvt:else>
                                          &nbsp;<mvt:eval expr="'- $' $ rnd(l.settings:option:price, 2)" />
                                      </mvt:if>
                                  </mvt:if>
                              </mvt:if>
                          </span>
                      </label>
                  </mvt:foreach>
              </div>
          <mvt:elseif expr="l.settings:attribute:type EQ 'select'">
              <div class="x-product-layout-purchase__options-attribute o-layout__item">
                  <label class="c-form-label &mvt:required_attribute_classes;" for="&mvt:attribute_ID;" title="&mvt:attribute:prompt;">&mvt:attribute:prompt;</label>
                  <div class="c-form-select">
                      <select id="&mvt:attribute_ID;" class="c-form-select__dropdown c-form-input--large" data-attribute="&mvte:attribute:code;" name="Product_Attributes[&mvt:attribute:index;]:value" &mvt:required_attribute;>
                          <mvt:foreach iterator="option" array="attribute:options">
                              <mvt:if expr="((g.Product_Attributes[l.settings:attribute:index]:value EQ 0) AND (l.settings:option:id EQ l.settings:attribute:default_id)) OR (g.Product_Attributes[l.settings:attribute:index]:value EQ l.settings:option:code)">
                                  <option value="&mvte:option:code;" data-option-price="&mvt:option:price;" data-regular-price="" selected>
                                      &mvte:option:prompt;
                                      <mvt:if expr="l.settings:option:price">
                                          <mvt:if expr="l.settings:option:price GT 0">
                                              &nbsp;<mvt:eval expr="' +$' $ rnd(l.settings:option:price, 2)" />
                                          <mvt:else>
                                              &nbsp;<mvt:eval expr="' -$' $ rnd(l.settings:option:price, 2)" />
                                          </mvt:if>
                                      </mvt:if>
                                  </option>
                              <mvt:else>
                                  <option value="&mvte:option:code;" data-option-price="&mvt:option:price;" data-regular-price="">
                                      &mvte:option:prompt;
                                      <mvt:if expr="l.settings:option:price">
                                          <mvt:if expr="l.settings:option:price GT 0">
                                              &nbsp;<mvt:eval expr="' +$' $ rnd(l.settings:option:price, 2)" />
                                          <mvt:else>
                                              &nbsp;<mvt:eval expr="' -$' $ rnd(l.settings:option:price, 2)" />
                                          </mvt:if>
                                      </mvt:if>
                                  </option>
                              </mvt:if>
                          </mvt:foreach>
                      </select>
                  </div>
              </div>
          <mvt:elseif expr="l.settings:attribute:type EQ 'swatch-select'">
              <div class="x-product-layout-purchase__options-attribute o-layout__item">
                  <label class="c-form-label &mvt:required_attribute_classes;" for="&mvt:attribute_ID;" title="&mvt:attribute:prompt;">&mvt:attribute:prompt; <span data-hook="attribute-swatch-name">&nbsp;</span></label>
                  <div class="c-form-select u-hidden">
                      <select id="&mvt:attribute_ID;" class="c-form-select__dropdown c-form-input--large" data-attribute="&mvte:attribute:code;" data-hook="attribute-swatch-select" name="Product_Attributes[&mvt:attribute:index;]:value" &mvt:required_attribute;>
                          <mvt:foreach iterator="option" array="attribute:options">
                              <mvt:if expr="((g.Product_Attributes[l.settings:attribute:index]:value EQ 0) AND (l.settings:option:id EQ l.settings:attribute:default_id)) OR (g.Product_Attributes[l.settings:attribute:index]:value EQ l.settings:option:code)">
                                  <option value="&mvte:option:code;" data-option-price="&mvt:option:price;" data-regular-price="" selected>
                                      &mvte:option:prompt;
                                      <mvt:if expr="l.settings:option:price">
                                          <mvt:if expr="l.settings:option:price GT 0">
                                              &nbsp;<mvt:eval expr="' +$' $ rnd(l.settings:option:price, 2)" />
                                          <mvt:else>
                                              &nbsp;<mvt:eval expr="' -$' $ rnd(l.settings:option:price, 2)" />
                                          </mvt:if>
                                      </mvt:if>
                                  </option>
                              <mvt:else>
                                  <option value="&mvte:option:code;" data-option-price="&mvt:option:price;" data-regular-price="">
                                      &mvte:option:prompt;
                                      <mvt:if expr="l.settings:option:price">
                                          <mvt:if expr="l.settings:option:price GT 0">
                                              &nbsp;<mvt:eval expr="' +$' $ rnd(l.settings:option:price, 2)" />
                                          <mvt:else>
                                              &nbsp;<mvt:eval expr="' -$' $ rnd(l.settings:option:price, 2)" />
                                          </mvt:if>
                                      </mvt:if>
                                  </option>
                              </mvt:if>
                          </mvt:foreach>
                      </select>
                  </div>
                  <div id="swatches" class="x-product-layout-purchase__swatches"></div>
              </div>
          <mvt:elseif expr="l.settings:attribute:type EQ 'checkbox'">
              <div class="x-product-layout-purchase__options-attribute o-layout__item">
                  <span class="c-form-label u-block">&nbsp;</span>
                  <label class="c-form-checkbox &mvt:required_attribute_classes;" title="&mvte:attribute:prompt;">
                      <mvt:if expr="g.Product_Attributes[l.settings:attribute:index]:value">
                          <input class="c-form-checkbox__input" data-attribute="&mvte:attribute:code;" data-option-price="&mvt:attribute:price;" data-regular-price="" type="checkbox" name="Product_Attributes[&mvte:attribute:index;]:value" value="Yes" checked &mvt:required_attribute;>
                      <mvt:else>
                          <input class="c-form-checkbox__input" data-attribute="&mvte:attribute:code;" data-option-price="&mvt:attribute:price;" data-regular-price="" type="checkbox" name="Product_Attributes[&mvte:attribute:index;]:value" &mvt:required_attribute;>
                      </mvt:if>
                      <span class="c-form-checkbox__caption">
                          <mvt:if expr="l.settings:attribute:image">
                              <img src="&mvte:attribute:image;" alt="&mvte:attribute:prompt;" title="&mvte:attribute:prompt;">
                          <mvt:else>
                              &mvte:attribute:prompt;
                              <mvt:if expr="l.settings:attribute:price">
                                  <mvt:if expr="l.settings:attribute:price GT 0">
                                      &nbsp;<mvt:eval expr="' +$' $ rnd(l.settings:attribute:price, 2)" />
                                  <mvt:else>
                                      &nbsp;<mvt:eval expr="' -$' $ rnd(l.settings:attribute:price, 2)" />
                                  </mvt:if>
                              </mvt:if>
                          </mvt:if>
                      </span>
                  </label>
              </div>
          </mvt:if>
      </mvt:foreach>
      <mvt:if expr="l.settings:subscription:enabled AND l.settings:subscription:term_count">
          <div class="x-product-layout-purchase__options-attribute o-layout__item">
              <mvt:if expr="l.settings:subscription:mandatory">
                  <label class="c-form-label &mvt:required_attribute_classes;" for="l-subscription" title="Subscribe">Select Subscription</label>
                  <div class="c-form-select">
                      <select id="l-subscription" class="c-form-select__dropdown" name="Product_Subscription_Term_ID" &mvt:required_attribute;>
                          <mvt:foreach iterator="term" array="subscription:terms">
                              <option value="&mvte:term:id;">&mvte:term:descrip;</option>
                          </mvt:foreach>
                      </select>
                  </div>
              <mvt:else>
                  <label class="c-form-label" for="l-subscription" title="Subscribe">Select Subscription</label>
                  <div class="c-form-select">
                      <select id="l-subscription" class="c-form-select__dropdown" name="Product_Subscription_Term_ID">
                          <option value="0">One Time Purchase</option>
                          <mvt:foreach iterator="term" array="subscription:terms">
                              <option value="&mvte:term:id;">&mvte:term:descrip;</option>
                          </mvt:foreach>
                      </select>
                  </div>
              </mvt:if>
          </div>
      </mvt:if>
      <input data-hook="product-attribute__count" type="hidden" name="Product_Attribute_Count" value="<mvt:eval expr="miva_array_elements(l.settings:attributes)" />">

      Comment


      • The only error that I see on that page is an icon error.

        Comment


        • Try updating your Attribute Machine code to the following:
          Code:
          AttributeMachine.prototype.Generate_Discount = function (discount) {
              var discount_div;
          
              discount_div = document.createElement('div');
              discount_div.innerHTML = discount.descrip + ': ' + discount.formatted_discount;
          
              return discount_div;
          };
          
          AttributeMachine.prototype.Generate_Swatch = function (product_code, attribute, option) {
              var swatch_container = document.querySelector('#&mvt:attributemachine:swatch_element_id;');
              var swatch = document.createElement('li');
              var img = document.createElement('img');
          
              img.src = option.image;
              img.setAttribute('alt', option.prompt);
              img.setAttribute('title', option.prompt);
              swatch.classList.add('o-list-inline__item');
              swatch.setAttribute('data-code', option.code);
              swatch.setAttribute('data-color', option.prompt);
              swatch.appendChild(img);
          
              setTimeout(function () {
                  if (swatch_container) {
                      var swatch_element = swatch_container.querySelector('ul');
                      var swatch_select = document.querySelector('[data-hook="attribute-swatch-select"]');
                      var swatch_selected = swatch_select.options[swatch_select.selectedIndex].text;
                      var swatch_name_element = document.querySelector('[data-hook="attribute-swatch-name"]');
                      var swatchElements = swatch_element.querySelectorAll('li');
          
                      swatch_element.removeAttribute('style');
                      swatch_element.classList.add('o-list-inline');
                      /**
                       * Adds the selected swatch name to the label.
                       */
                      swatch_name_element.textContent = swatch_selected;
          
                      /**
                       * Adds an active class to the selected swatch.
                       */
                      swatchElements.forEach(function (swatchElement) {
                          var swatchColor = swatchElement.getAttribute('data-code');
                          var swatchImage = swatchElement.querySelector('img');
          
                          if (swatchColor === swatch_select.options[swatch_select.selectedIndex].value) {
                              swatchImage.classList.add('x-product-layout-purchase__swatches--active');
                          }
                      });
                  }
              }, 0);
          
              return swatch;
          };
          
          AttributeMachine.prototype.Swatch_Click = function(input, attribute, option) {
              var swatch_name_element = document.querySelector('[data-hook="attribute-swatch-name"]');
              var i;
          
              for (i = 0; i < input.select.options.length; i++) {
                  if (input.select.options[i].value === option.code) {
                      input.select.selectedIndex = i;
                  }
              }
          
              if (attribute.inventory) {
                  this.Attribute_Changed(input);
              }
          
              swatch_name_element.innerHTML = option.prompt;
          };
          Matt Zimmermann
          Director of UI/UX Standards and Theme Development
          / Miva, Inc.

          Comment


          • well shoot! tried replacing that code hoping it would magically fix itself, but no luck.
            Image still swaps itself out, but that elusive CSS selector doesn't get applied to the image to get the highlight. I've got to be missing something. Any other suggestions as to where to look?

            Comment


            • Add this class to your theme-styles.css...I may have forgotten to mention this.
              Code:
              .x-product-layout-purchase__swatches--active {
                  box-shadow: 0 0 0 2px #eaeaea, 0 0 3px 3px #707070;
              }
              Matt Zimmermann
              Director of UI/UX Standards and Theme Development
              / Miva, Inc.

              Comment


              • Yay Matt!!!! Thank you for your help. I made your changes and nothing happened, but magically this morning all the caches cleared and the planets aligned and the highlight is in place.

                Not sure what the client did to take that out, but all is aok now.

                I appreciate your willingness to help.

                Patty

                Comment

                Working...
                X

                This website uses cookies to identify visitors, track visitors to our website, store login session information and to remember your user preferences. By continuing to use this site you agree to our use of cookies. Learn More.

                This website uses cookies. By continuing to use this site you agree to our use of cookies. Learn More.

                Accept