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!

    #2
    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

    Miva Web Developer
    Alchemy Web Development
    https://www.alchemywebdev.com
    Site Development - Maintenance - Consultation

    Miva Certified Developer
    Miva Professional Developer

    https://www.dev4web.net | Twitter

    Comment


      #3
      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


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

        Comment


          #5
          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

          Miva Web Developer
          Alchemy Web Development
          https://www.alchemywebdev.com
          Site Development - Maintenance - Consultation

          Miva Certified Developer
          Miva Professional Developer

          https://www.dev4web.net | Twitter

          Comment


            #6
            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


              #7
              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

              Miva Web Developer
              Alchemy Web Development
              https://www.alchemywebdev.com
              Site Development - Maintenance - Consultation

              Miva Certified Developer
              Miva Professional Developer

              https://www.dev4web.net | Twitter

              Comment


                #8
                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