Migrating Recharge theme

In the case that you are migrating from ReCharge and would like to keep your current plan picker widget styling - you can try replacing your skio-plan-picker.liquid and skio-plan-picker-rewrites.liquid code with the code blocks shown below. Please note - additional styling may still be needed after replacing the code blocks. Also, the below code snippets won't work if your current ReCharge widget is being auto-injected into the page (in that case you'll need to use Skio's boilerplate code).

skio-plan-picker.liquid

Replace your skio-plan-picker.liquid code with the code block below:

{% if product and product.selling_plan_groups.size > 0 %}
            <style>
              .available {
                display: initial;
              }
              .unavailable {
                display: none;
              }
              .selectric-wrapper {
                width: 100%;
              }
              fieldset#rc_container{display:block;clear:both;width:100%;flex:none;margin-bottom:1em}fieldset#rc_container>.select-wrapper{display:none}#rc_duplicateSelect,#rc_shipping_interval_unit_type,#rc_subscription_id{display:none!important}label.rc_label{vertical-align:middle;display:inline!important;float:none!important;line-height:2!important;padding-left:0}label.rc_label__deliver_every{margin-top:0;margin-bottom:0;display:inline-block!important;padding:8px 0 0 23px}.rc_subscription-only label.rc_label__deliver_every{padding-left:0}span.rc_label__delivery{padding-right:4px}input.rc_radio{vertical-align:middle;margin:0 3px 0 0;padding:0 5px 0 0;width:16px;-webkit-appearance:radio;float:none!important}input.rc_radio:focus{outline:0}select.rc_select{margin-bottom:0;vertical-align:middle;max-width:100%;font-size:100%;display:initial}div.rc_block{white-space:nowrap}div.rc_block__type{width:100%;margin:0;border-radius:4px;padding:8px}.rc_subscription-only div.rc_block__type{padding-left:0}div.rc_block__type__options{display:none}.rc_subscription-only div.rc_block__type__options,div.rc_block__type--active div.rc_block__type__options,div.rc_popup{display:block}div.rc_popup{white-space:nowrap;padding:8px}.rc_subscription-only div.rc_popup{padding:0}div.rc_block__type--active+div.rc_popup{margin-top:8px}a.rc_popup__hover,div.rc_popup__hover{display:inline-block;position:relative;height:35px;clear:both;cursor:pointer}img.rc_popup__icon{display:inline-block;vertical-align:middle;position:relative;height:21px;top:-2px;margin-right:3px;-ms-interpolation-mode:bicubic;image-rendering:unset}div.rc_popup__block{display:none;position:absolute;top:100%;cursor:default;left:0;text-align:left;white-space:normal}div.rc_popup__block:before{display:block;content:"";width:1px;border:10px solid transparent;position:absolute;top:-20px;left:0}div.rc_popup__block:hover,div.rc_popup__hover:hover .rc_popup__block{display:block}div.rc_popup__hover--mobile div.rc_popup__block:hover{display:none}div.rc_popup__block{width:300px;padding:0}div.rc_popup__close{display:block;width:40px;height:40px;position:absolute;top:0;right:0;font-size:23px;text-align:center;line-height:40px;z-index:300;cursor:pointer;font-family:arial}div.rc_popup__block__content{white-space:normal;padding:20px}div.rc_popup__block__content a{text-decoration:none}div.rc_popup__block__footer{padding:0;margin-bottom:25px;text-align:right;height:28px}div.rc_popup__block__footer a{display:block;border:none}img.rc_popup__badge{height:28px;margin-left:auto;margin-right:0;-ms-interpolation-mode:bicubic;image-rendering:unset}form[action^="/cart/add"] [type=submit]{visibility:visible !important}.rc_reverse-options{display:flex;flex-direction:column-reverse}#rc_container+script+.selector-wrapper{margin-top:10px}#rc_container .jumpstart-selector{margin-top:8px}#addToCartForm #rc_container .rc_select{max-width:100%}#productPrice-product-template small{display:none}.rc_theme--lookbook div.rc_popup__block{width:250px}.rc_theme--lookbook select.rc_select{width:auto;padding-right:25px}.rc_theme--california label.rc_label:after{display:none}.rc_theme--mobilia select.rc_select__frequency{margin-right:15px}.rc_theme--mobilia select.rc_select{padding-right:33px}.rc_theme--radiance #product-actions{overflow:visible}.rc_theme--prestige form[action^="/cart/add"] [type=submit]{visibility:visible}
            </style>
            {% assign variantPrice = product.selected_or_first_available_variant.price %}
            <fieldset id="rc_container" class="skio-plan-picker" style="display: none;padding: 0;border: none;margin-bottom: 40px;margin-top: 10px">
              <input type="hidden" name="selling_plan" value="{{ product.selected_selling_plan.id }}" />
              {% for group in product.selling_plan_groups %}
                {% assign sellingPlanPrice = group.selling_plans[0].price_adjustments[0].value %}
                {% assign variantPriceFloat = variantPrice | times: 1.0 %}
                {% assign sellingPlanPriceFloat = sellingPlanPrice | times: 1.0 %}
                {% assign savingsFlat = variantPriceFloat | minus: sellingPlanPriceFloat %}
                {% assign savings = savingsFlat | times: 100.0 | divided_by: variantPriceFloat | round %}
                <div name="skio-subscription">
                  <div class="block rc_block rc_block__type rc_block__type__autodeliver rc_block__type--active" style="">
                    <input type="radio" name="skio-subscription-value" id="{{ group.id }}" name="skio-subscription-value" value="{{ group.id }}" class="rc_radio rc_radio__autodeliver">
                    <label for="{{ group.id }}" class="rc_label rc_label__autodeliver">
                      Subscribe and Save
                      <span class="rc_label__discount">{{ savings }}%</span>
                      <span id="rc_price_autodeliver" class="rc_price rc_price__autodeliver">{{ product.selected_or_first_available_variant.selling_plan_allocations[0].price | money }}</span>
                      <div>
                        <select style="display: none">
                          {% for plan in group.selling_plans %}
                            <option value="{{ plan.id }}">{{ plan.options[0].value }}</option>
                          {% endfor %}
                        </select>
                      </div>
                    </label>   
                  </div>     
                </div>
              {% endfor %}
              {% unless product.requires_selling_plan %}
                <div name="skio-one-time">
                  <div style="    border-radius: 5px 5px 0 0;" class="block rc_block rc_block__type rc_block__type__onetime">
                    <input type="radio" id="rc_purchase_type_onetime" name="skio-subscription-value" value="onetime" class="rc_radio rc_radio__onetime">
                    <label for="rc_purchase_type_onetime" class="rc_label rc_label__onetime">
                      One-time purchase
                      <span id="rc_price_onetime" class="rc_price rc_price__onetime">{{ product.selected_or_first_available_variant.price | money }}</span>
                    </label>
                  </div>
                </div>
              {% endunless %}
            </fieldset>
            <script>
              var product = {{ product | json }};
              var selling_plans_by_id = {};
              product.selling_plan_groups.forEach(function (group) {
                group.selling_plans.forEach(function (plan) {
                  selling_plans_by_id[plan.id] = plan;
                  selling_plans_by_id[plan.id].selling_plan_group_id = group.id;
                })
              });
          
              var variants_by_id = {};
              {% for variant in product.variants %}
                {% assign variant_id = variant.id %}
                variants_by_id[{{ variant_id }}] = {{ variant | json }};
                variants_by_id[{{ variant_id }}].price = {{ variant.price | money | json }};
                variants_by_id[{{ variant_id }}].group_ids = {};
                variants_by_id[{{ variant_id }}].selling_plans = {};
          
                {% for alloc in variant.selling_plan_allocations %}
                  variants_by_id[{{ variant_id }}].group_ids[{{ alloc.selling_plan_group_id | json }}] = true;
                  variants_by_id[{{ variant_id }}].selling_plans[{{ alloc.selling_plan.id }}] = {};
                  variants_by_id[{{ variant_id }}].selling_plans[{{ alloc.selling_plan.id }}].price = {{ alloc.price | money | json }};
                {% endfor %}
              {% endfor %}
          
              product.selected_selling_plan = {{ product.selected_selling_plan | json }};
              product.selling_plans_by_id = selling_plans_by_id;
              product.variants_by_id = variants_by_id;
              
              if (document.currentScript) {
                document.currentScript.previousElementSibling.dataset.product = JSON.stringify(product);
              }
            </script>
          {% endif %}
          

skio-plan-picker-rewrites.liquid

Replace your skio-plan-picker-rewrites.liquid code with the code block below:

<script>
            function patchRequests() {
              const XHRSend = XMLHttpRequest.prototype.send;
              XMLHttpRequest.prototype.send = function (...args) {
                args[0] = reserialize(args[0]);
                return XHRSend.apply(this, args);
              };
            
              const windowFetchCopy = window.fetch;
              window.fetch = function (...args) {
                if (args[1] && args[1].body) {
                  args[1].body = reserialize(args[1].body);
                }
                return windowFetchCopy(...args);
              };
            }
            
             function XMLHttpRequestPromise(obj) {
              return new Promise((resolve, reject) => {
                const xhr = new XMLHttpRequest();
                xhr.open(obj.method || 'GET', obj.url);
                if (obj.headers) {
                  Object.keys(obj.headers).forEach((key) => {
                    xhr.setRequestHeader(key, obj.headers[key]);
                  });
                }
                xhr.onload = () => {
                  if (xhr.status >= 200 && xhr.status < 300) {
                    resolve(xhr.response);
                  } else {
                    reject(xhr.statusText);
                  }
                };
                xhr.onerror = () => reject(xhr.statusText);
                xhr.send(obj.body);
              });
            }
          
            function reserializeJSON(json) {
              try {
                const body = JSON.parse(json);
                const id = body.id;
                const lineItems = (body.checkout || {}).line_items;
                if (id) {
               const planId = getPlanId(document);
                if (planId) {
                body['selling_plan'] = planId;
                }
                } else if (lineItems) {
                  body.checkout.line_items = lineItems.map((item) => {
                    const { variant_id: id } = item;
                    if (!id) {
                      return item;
                    }
                
                const planId = getPlanId(document);
                    if (planId) {
                      item.properties['selling_plan'] = planId;
                    }
                    return item;
                  });
                }
                const reserializedBody = JSON.stringify(body);
                return reserializedBody;
              } catch (e) {
                return json;
              }
            }
            
            function reserializeFormData(formData) {
              try {
                if (!formData.get('selling_plan')) {
                  const planId = getPlanId(document);
                  if (planId) {
                    formData.append('selling_plan', planId);
                  }
                }
              } catch(e) {}
              return formData;
            }
            
            function reserializeQueryParam(body) {
              try {
                const reserializedBody = body.split('&').map((field) => {
                  return field;
                });
                if (!body.includes('selling_plan') && planId) {
                  const planId = getPlanId(document);
                  if (planId) {
                    reserializedBody.push('selling_plan=' + planId);
                    }
                  }
                return reserializedBody.join('&');
              } catch (e) {
                return body;
              }
            }
            
            function reserialize(body) {
              try {
                if (!body) {
                  return body;
                }
                if (typeof body === 'string') {
                  let isJson = false;
                  try {
                    JSON.parse(body);
                    isJson = true;
                  } catch (e) {}
                  return isJson ? reserializeJSON(body) : reserializeQueryParam(body);
                } else if (typeof body === 'object' && body.entries && body.entries()) {
                  return reserializeFormData(body);
                }
              } catch (e) {}
              return body;
            }  
          
            function extractContent(s) {
              var span = document.createElement('span');
              span.innerHTML = s;
              return span.textContent || span.innerText;
            };
            function updatePrice(planSelector) {
              return;
              var product = JSON.parse(planSelector.dataset.product);
              var planId = getPlanId(planSelector);
              var variantId = getVariantId(planSelector);
              if (!variantId) {
                return;
              }
              var variant = product.variants_by_id[variantId];
              planId = planId ? parseInt(planId) : null;
              var price = planId && variant.selling_plans[planId]
                ? variant.selling_plans[planId].price 
                : variant.price;
                var varPrice = parseFloat(extractContent(variant.price).replace(', '').replace(',', ''))
                var sellingPrice = Object.values(variant.selling_plans)[0].price
                var sellingPriceFloat = parseFloat(extractContent(Object.values(variant.selling_plans)[0].price).replace(', '').replace(',', ''))
                var savings = ((varPrice - sellingPriceFloat) / varPrice * 100).toFixed(0);
              var selectors = [
                '#ProductPrice',
                '#productPrice-product-template',
                '#ProductPrice-product-template',
                '#productPrice > .visually-hidden',
                '.price .price-item--regular',
                '.product__price .price-item--regular',
                '.product__price .product__price--reg',
                '.product__price .product__current-price',
                '.product-single__price',
                '[id^=productPrice-]',
                '.price .money',
                '.product__price',
                '[data-product-price]',
                '.current_price .money'
              ].join(',');
              var wrapper = planSelector.closest('div[data-section-type], .shopify-section');
              if (!wrapper || !wrapper.length) {
                wrapper = document.body;
              }
              var priceContainers = wrapper.querySelectorAll(selectors);
              priceContainers.forEach(function rewritePrice(container) {
                if (extractContent(container.innerHTML) !== extractContent(price.toString())) {
                  container.innerHTML = price;
                }
              });
          
              /*var oneTimes = planSelector.querySelectorAll('.one-time-price');
              oneTimes.forEach(function(oneTime) {
                const newText = `One-time Purchase: ${variant.price}`;
                if (oneTime.textContent !== newText) {
                  oneTime.textContent = newText;
                }
              });
              var subscribeAndSaves = planSelector.querySelectorAll('.subscribe-price');
              subscribeAndSaves.forEach(function(subscribeAndSave) {
                const newText = `Subscribe & Save (${savings}%): ${sellingPrice}`;
                if (subscribeAndSave.textContent !== newText) {
                  subscribeAndSave.textContent = newText;
                }
              }); */
            }
          
            function updateSellingPlanFormId(planSelector) {
              var planId = getPlanId(planSelector);
              var sellingPlanFormId = planSelector.querySelector('[name="selling_plan"]');
              if (!sellingPlanFormId) {
                return;
              }
              var noValueAndNoPlan = planId == null && sellingPlanFormId.value === '';
              if (sellingPlanFormId.value != planId && !noValueAndNoPlan) {
                sellingPlanFormId.value = planId;
              }
            }
          
            function filterGroupsForVariantAndThenUpdate(planSelector) {
              console.log('filtering');
              var variantId = getVariantId(planSelector);
              if (!variantId) {
                return;
              }
              var product = JSON.parse(planSelector.dataset.product);
              var variant = product.variants_by_id[variantId];
              let hasSubscriptionAvailable = false;
              planSelector.querySelectorAll('[name="skio-subscription"]').forEach(function(node) {
                var groupId = node.querySelector('[name="skio-subscription-value"]').value;
                var isAvailable = Boolean(groupId && variant && variant.group_ids && variant.group_ids[groupId]);
                if (isAvailable) {
                  hasSubscriptionAvailable = true;
                  if (node.className !== 'available') {
                    node.className = 'available';
                    //checkPlanOnSelect();
                  }
                } else if (node.className !== 'unavailable') {
                  node.className = 'unavailable';
                }
              });
          
              planSelector.querySelectorAll('[name="skio-one-time"]').forEach(function(node) {
                var isAvailable = !product.requires_selling_plan && hasSubscriptionAvailable;
                if (isAvailable) {
                  if (node.className !== 'available') {
                    node.className = 'available';
                  }
                } else if (node.className !== 'unavailable') {
                  node.className = 'unavailable';
                }
              });
          
              updatePrice(planSelector);
              updateSellingPlanFormId(planSelector);
              updateCheckedSellingPlanGroup(planSelector)
            }
          
            function getPlanId(planSelector) {
              try {
                var form = planSelector.closest('form[action*="/cart/add"]');
                var subscription = form.querySelector('.available[name="skio-subscription"] select');
                var subscriptionChecked = form.querySelector('.available[name="skio-subscription"] [name="skio-subscription-value"]').checked;
                if (subscription && subscriptionChecked) {
                  return parseInt(subscription.value);
                }
              } catch {}
               return null;
            }
          
            function getVariantId(planSelector) {
              try {
                var form = planSelector.closest('form[action*="/cart/add"]');
                var input = form.querySelector('select[name="id"],input[name="id"],button[name="id"]');
                return parseInt(input.value);
              } catch(e) {
                return null;
              }
            }
          
            function updateCheckedSellingPlanGroup(planSelector) {
              var planId = getPlanId(planSelector);
              var form = planSelector.closest('form[action*="/cart/add"]');
              if (planId) {
                var subscription = form.querySelector('.available[name="skio-subscription"] [name="skio-subscription-value"]');
                if (subscription && subscription.checked !== true) {
                  subscription.checked = true;
                }
                form.querySelectorAll('[data-skio-plan-options]').forEach(function(a) {
                  if (a && a.style.display !== 'flex') {
                    a.style.display = 'flex';
                  }
                })
              } else {
                var oneTime = form.querySelector('.available[name="skio-one-time"] [name="skio-subscription-value"]');
                if (oneTime && oneTime.checked !== true) {
                  oneTime.checked = true;
                }
                form.querySelectorAll('[data-skio-plan-options]').forEach(function(a) {
                  if (a && a.style.display !== 'none') {
                    a.style.display = 'none';
                  }
                })
              }
            }
          
            function addObserver(planSelector) {
              const rewriteObserver = new MutationObserver(function(mutations) {
                filterGroupsForVariantAndThenUpdate(planSelector);
                /*if (window.swatchSelected) {
                  checkPlanOnSelect(planSelector);
                  window.swatchSelected = false;
                }*/
              });
              rewriteObserver.observe(document, {
                childList: true,
                subtree: true,
                attributes: true,
              });
            }
          
            function setupPlanSelector(planSelector) {
              var product = JSON.parse(planSelector.dataset.product);
              filterGroupsForVariantAndThenUpdate(planSelector);
              planSelector.style.display = 'initial';
            }
          
            function checkPlanOnSelect(planSelector) {
              console.log('planSelector', planSelector);
              var form = planSelector ? planSelector.closest('form[action*="/cart/add"]') : document;
              var subscriptionRadioBox = form.querySelector('.available[name="skio-subscription"] [name="skio-subscription-value"]');
              console.log('subscriptionRadioBox', subscriptionRadioBox);
              if (subscriptionRadioBox && !subscriptionRadioBox.checked) {
                subscriptionRadioBox.checked = true;
              }
            }
          
            function selectBlocks(selectedBlock, planSelector) {
              var parentBlocks = planSelector.querySelectorAll('.rc_block');
              parentBlocks.forEach(function(block) {
                if (block !== selectedBlock && block.className.includes('rc_block__type--active')) {
                  block.classList.remove('rc_block__type--active');
                }
              })
              if (!selectedBlock.className.includes('rc_block__type--active')) {
                selectedBlock.classList.add('rc_block__type--active');
              }
              filterGroupsForVariantAndThenUpdate(planSelector);
            }
          
            // check all sub boxes
            function initialCheckPlanOnSelect() {
              var subscriptionRadioBoxes = document.querySelectorAll('[name="skio-subscription"] [name="skio-subscription-value"]');
              subscriptionRadioBoxes.forEach(function (subscriptionRadioBox) {
                if (!subscriptionRadioBox.checked) {
                  subscriptionRadioBox.checked = true;
                }
              });
            }
          
            function onLoad() {
              patchRequests();
              document.querySelectorAll('fieldset.skio-plan-picker').forEach(function (planSelector) {
                setupPlanSelector(planSelector);
                addObserver(planSelector);
                initialCheckPlanOnSelect();
                planSelector.querySelectorAll('[name="skio-subscription-value"]').forEach(function(node) {
                  node.addEventListener('change', function (e) {
                    filterGroupsForVariantAndThenUpdate(planSelector);
                  });
                });
                /* planSelector.querySelectorAll('select').forEach(function(node) {
                  node.addEventListener('change', function (e) {
                    checkPlanOnSelect(planSelector);
                    filterGroupsForVariantAndThenUpdate(planSelector);
                  });
                }); */
                var parentBlocks = document.querySelectorAll('.block');
                console.log('parentBlocks', parentBlocks);
                parentBlocks.forEach(function (parentBlock) {
                  parentBlock.addEventListener('click', function(e) {
                    if (parentBlock.closest('.available')) {
                      selectBlocks(parentBlock, planSelector);
                    }
                  });
                });
                document.querySelector(".current_price .money").innerHTML =  document.querySelector("#rc_price_autodeliver").textContent;
              });
            }
           
            if (document.readyState !== 'loading') {
              onLoad();
            } else {
              window.addEventListener('DOMContentLoaded', function () {
                onLoad();
              });
            }
          </script>
          

How did we do?


Powered by HelpDocs (opens in a new tab)