I need to refresh cart popup when product is added

PamDigital
Shopify Partner
66 2 12

Hey there, I am working on a custom theme. My problem is I want to show product price - cart total = discount amount on cart popup. So when I added product to cart it doesn't show the discount amount untill I refresh the page. After refreshing the page cart popup shows the discount amount. What I want is to refresh the cart popup when product is added without refreshing the whole page.
Is there any js for that? Like if product is added to cart refresh the cart popup.

{% if settings.language_switcher_enabled %}

<div class="translation-lab-language-switcher {{ settings.language_switcher_position }}">
  <div class="translation-lab-dropdown">
    {% if settings.language_switcher_flags %}
    <img class="language-flag" src="{{ 'tlab-flags-' | append: request.locale.iso_code | append: '.png' | asset_url }}">
    {% endif %}
  </div>
  <ul class="translation-lab-language-options {{ settings.language_switcher_position }}">
    {%- for locale in shop.published_locales -%}
    <li class="language-option {% if routes.root_url == locale.root_url %}active{% endif %}" data-language-code="{{ locale.iso_code }}">
      {% if settings.language_switcher_flags %}
      <img class="language-flag" src="{{ 'tlab-flags-' | append: locale.iso_code | append: '.png' | asset_url }}">
      {% endif %}
      {% case settings.language_switcher_label %}
      {% when 'language-name' %}
      <span class="language-label language-name">{{ locale.endonym_name | split: '(' | first | strip }}</span>
      {% when 'language-code' %}
      <span class="language-label language-code">{{ locale.iso_code | split: '-' | first | strip }}</span>
      {% endcase %}
    </li>
    {%- endfor %}
  </ul>
</div>

{% if request.design_mode %}

{% endif %}

{{ 'translation-lab-language-switcher-floating.css' | asset_url | stylesheet_tag }}

<style>

  

  
  .translation-lab-language-switcher {
    background-color: {{ settings.language_switcher_background_color }} !important;
    border-color: {{ settings.language_switcher_border_color }} !important;
    border-width: {{ settings.language_switcher_border_width }}px !important;
    font-size: {{ settings.language_switcher_font_size }} !important;
    font-weight: {{ settings.language_switcher_font_weight }} !important;
  }

  .translation-lab-dropdown {
    color: {{ settings.language_switcher_text_color }} !important;
  }

  .translation-lab-dropdown:after {
    border-color: {{ settings.language_switcher_text_color }} !important;
  }

  .translation-lab-language-switcher.top-right {
    position: absolute;
    top: {{ settings.language_switcher_spacing_top }}px;
    bottom: auto;
    left: auto;
    right: {{ settings.language_switcher_spacing_right }}px;
  }

  .translation-lab-language-switcher.top-left {
    position: absolute;
    top: {{ settings.language_switcher_spacing_top }}px;
    bottom: auto;
    left: {{ settings.language_switcher_spacing_left }}px;
    right: auto;
  }

  .translation-lab-language-switcher.bottom-left {
    position: fixed !important;
    top: auto !important;
    bottom: {{ settings.language_switcher_spacing_bottom }}px !important;
    left: {{ settings.language_switcher_spacing_left }}px !important;
    right: auto !important;
  }

  .translation-lab-language-switcher.bottom-right {
    position: fixed !important;
    top: auto !important;
    bottom: {{ settings.language_switcher_spacing_bottom }}px !important;
    left: auto !important;
    right: {{ settings.language_switcher_spacing_right }}px !important;
  }

  {% if settings.language_switcher_custom_css != blank -%}
  {{- settings.language_switcher_custom_css -}}
  {%- endif %}

</style>

<script>

  // https://tc39.github.io/ecma262/#sec-array.prototype.find
  if (!Array.prototype.find) {
    Object.defineProperty(Array.prototype, 'find', {
      value: function(predicate) {
        // 1. Let O be ? ToObject(this value).
        if (this == null) {
          throw TypeError('"this" is null or not defined');
        }

        var o = Object(this);

        // 2. Let len be ? ToLength(? Get(O, "length")).
        var len = o.length >>> 0;

        // 3. If IsCallable(predicate) is false, throw a TypeError exception.
        if (typeof predicate !== 'function') {
          throw TypeError('predicate must be a function');
        }

        // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
        var thisArg = arguments[1];

        // 5. Let k be 0.
        var k = 0;

        // 6. Repeat, while k < len
        while (k < len) {
          // a. Let Pk be ! ToString(k).
          // b. Let kValue be ? Get(O, Pk).
          // c. Let testResult be ToBoolean(? Call(predicate, T, < kValue, k, O >)).
          // d. If testResult is true, return kValue.
          var kValue = o[k];
          if (predicate.call(thisArg, kValue, k, o)) {
            return kValue;
          }
          // e. Increase k by 1.
          k++;
        }

        // 7. Return undefined.
        return undefined;
      },
      configurable: true,
      writable: true
    });
  }

  (function () {

    function buildLanguageList() {
      var languageListJson = '[{%- for locale in shop.published_locales %}{\
"name": "{{locale.name | split: "(" | first | strip}}",\
"endonym_name": "{{ locale.endonym_name | split: "(" | first | strip}}",\
"iso_code": "{{ locale.iso_code }}",\
"primary": {{ locale.primary }},\
"flag": "{{ locale.iso_code | append: ".png" | asset_url }}"\
}{% unless forloop.last %},{% endunless -%}{%- endfor %}]';
      return JSON.parse(languageListJson);
    }

    function createDropdown(container, languageChangeHandler) {

      var dropdown = container.children[0];
      var span = dropdown.children[0];
      var selectedImg = dropdown.children[1];
      var ul = container.children[1];

      for (var i = 0; i < ul.children.length; i++) {
        var el = ul.children[i];
        el.onclick = languageChangeHandler(el.dataset.languageCode, el.children[0].innerText, languageChangeCallback);
      }

      var isOpen = false;

      dropdown.addEventListener('click', function (event) {
        event.preventDefault();
        isOpen = !isOpen;
        if (isOpen) {
          openDropdown();
        } else {
          closeDropdown();
        }
      });

      container.addEventListener('mouseleave', function () {
        closeDropdown();
      });

      function languageChangeCallback(lang, elementText) {
        closeDropdown();
        span.textContent = elementText;
        if (selectedImg) {
          selectedImg.src=lang.flag;
        }
      }

      function openDropdown() {
        isOpen = true;
        dropdown.classList.add('open');
        ul.classList.add('open');
      }

      function closeDropdown() {
        isOpen = false;
        dropdown.classList.remove('open');
        ul.classList.remove('open');
      }
    }

    function redirectUrlBuilderFunction(primaryLocale) {
      var shopDomain = 'https://{{shop.domain}}';
      if (window.Shopify.designMode) {
      	shopDomain = 'https://{{shop.permanent_domain}}';
      }
      var currentLocale = '{{request.locale.iso_code}}'.toLowerCase();
      var currentLocaleRegEx = new RegExp('^\/' + currentLocale, "ig");
      var primaryLocaleLower = primaryLocale.toLowerCase();
      var pathname = window.location.pathname;
      var queryString = window.location.search || '';
      return function build(redirectLocale) {
        if (!redirectLocale) {
          return null;
        }
        var redirectLocaleLower = redirectLocale.toLowerCase();
        if (currentLocale !== redirectLocaleLower) {
          if (redirectLocaleLower === primaryLocaleLower) {
            return shopDomain + pathname.replace(currentLocaleRegEx, '') + queryString;
          } else if (primaryLocaleLower === currentLocale) {
            return shopDomain + '/' + redirectLocaleLower + pathname + queryString;
          } else {
            return shopDomain + '/' + pathname.replace(currentLocaleRegEx, redirectLocaleLower) + queryString;
          }
        }
        return null;
      }
    }

    function configure() {
      var languageList = buildLanguageList();
      var primaryLanguage = languageList.find(function (x) { return x.primary; });
      if (!primaryLanguage && !primaryLanguage.iso_code) {
        // error: there should be atleast one language set as primary
        return;
      }

      var redirectUrlBuilder = redirectUrlBuilderFunction(primaryLanguage.iso_code);

      var containers = document.querySelectorAll('.translation-lab-language-switcher');
      if (containers && containers.length) {
        for (var i = 0; i < containers.length; i++) {
          createDropdown(containers[i], languageChangeHandler);
        }
      }

      function languageChangeHandler(languageCode, elementText, callback) {
        var selectedLanguage = languageList.find(function (language) { return language.iso_code.toLowerCase() === languageCode.toLowerCase() });
        return function () {
          callback(selectedLanguage, elementText);
          localStorage.setItem('translation-lab-lang', selectedLanguage.iso_code);
          var redirectUrl = redirectUrlBuilder(selectedLanguage.iso_code);
          redirectUrl && window.location.assign(redirectUrl);
        }
      }
    }

    configure();

  })();

</script>

{% endif %}

{% include 'product-grid-variables', ratio:'1:1' %}

<div id="cart" class="btn-group btn-block">
  <button type="button" data-toggle="dropdown" data-loading-text="{{ 'products.product.loading' | t }}" class="btn dropdown-toggle">
    <span id="cart-total">
      <span class="txt_number">{{ cart.item_count }}</span>
      <span class="txt_items">{{ 'cart.general.my_cart'| t }}</span>
      <span class="total-price">{{ item.line_price | money }}</span>
    </span>
  </button>
  <ul class="dropdown-menu pull-right">
    <li class="has-scroll">
      <table class="table">
        <tbody>
          {% if cart.item_count < 1 %} 
          <p class="text-center cart-empty">{{ 'cart.general.no_items'| t }}</p>
          {% else %}
          {% for item in cart.items %}
          <tr>
            <td class="text-center">
              <a href="{{ item.url }}">
                {% include 'product-grid-image',image:item.image, customclass:'cart-image' %}
              </a>
            </td>
            <td class="text-left info-item">
              <a class="cart-name" href="{{ item.url }}">{{ item.product.title }}</a>
              <p class="cart-quantity">{{ item.quantity }} &times;</p> 
              <p class="cart-price">{{ item.original_price | money }}</p> 
            
            </td>
            <td class="text-center cart-close">
              <button type="button" onclick="cart.remove('{{ item.variant_id }}');" title="Remove" class="btn btn-danger btn-xs">
                <i class="fa fa-angle-trash-alt"></i>
              </button>
            </td>
            
          </tr>
          {% endfor %}
          {% endif %}
        </tbody>
      </table>
    </li>
    <li {% if cart.item_count < 1 %} class="hide"{% endif %}>
      <table class="table">
        <tr>
          <td class="text-left">{{ 'cart.general.subtotal' | t }} :</td>
          <td class="text-right" id="cart-discount"> {{ cart.total_discount | money }}</td>
          <td class="text-right" id="cart-subtotal"> {{ cart.total_price | money }}</td>
        </tr>
      </table>
      <p class="text-center cart-button">
        <a href="/checkout">{{ 'cart.general.checkout' | t }}</a>
      </p>
    </li>
  </ul>
</div>

 

Replies 2 (2)

PamDigital
Shopify Partner
66 2 12

And this is my ajax cart

  // product page add to cart
  $('#button-cart').on('click', function(e) {
    e.preventDefault();
    $.ajax({
      url: '/cart/add.js',
      type: 'post',
      data: $('#form_buy input[type=\'text\'], #form_buy select'),
      dataType: 'json',
      beforeSend: function() {
        $('#button-cart').button('loading');
      },
      complete: function() {
        $('#button-cart').button('reset');
      },
      success: function(json) {
        $('.alert, .text-danger').remove();
        $('.form-group').removeClass('has-error');

        if (json['error']) {
          if (json['error']['option']) {
            for (i in json['error']['option']) {
              var element = $('#input-option' + i.replace('_', '-'));
              if (element.parent().hasClass('input-group')) {
                element.parent().after('<div class="text-danger">' + json['error']['option'][i] + '</div>');
              } else {
                element.after('<div class="text-danger">' + json['error']['option'][i] + '</div>');
              }
            }
          }

          if (json['error']['recurring']) {
            $('select[name=\'recurring_id\']').after('<div class="text-danger">' + json['error']['recurring'] + '</div>');
          }

          // Highlight any found errors
          $('.text-danger').parent().addClass('has-error');
        }

        toastr.success('{{ 'cart.general.item_added' | t }}');

                       $.getJSON('/cart.js', function(cart) {
          load(cart);
          buildMiniCart();
        });

        $('html, body').animate({ scrollTop: 0 }, 'slow');

      },
      error: function(xhr, ajaxOptions, thrownError) {
        if(xhr.status == 422 ) {
          toastr.warning('{{ 'cart.general.item_added_402' | t }}');
                         } else {
                         alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
        }
      }
    });
  });
David_Weru
Shopify Partner
177 16 43

Hello, PamDigital!

  I've dealt with cartjs and cart updates.  I can work with you to make the updates automatic without the update button.

 

  Your update will have to be triggered recursively via a callback.  If you'd like, I can modify and license a proprietary js function class for use.

 

 Please message me for more information.