1

I am trying to add a little line in my Shopify product page where it will show the customer the amount currently in his/her cart, and automatically show whether or not the customer is eligible for free shipping, and the amount needed to hit free shipping.

I have managed to do all the above, with one small problem now: when the customer hits add to cart, the line still shows the same thing until the customer refreshes the page. I did a bit of reading and relaised it's because the cart works on something called AJAX.

I am not a programmer or developer, I am just a site owner, and I have very little knowledge of coding. I just google for solutions and copy and paste and modify code to get my desired effect. But this one really has me stumped, so i appreciate if someone can help me out!

Thank you in advance!

Also I apologise if my code looks messy or I sound like I don't know what I'm talking about. I'm really new to this!

<div id="freeship" style="font-weight:bold; padding: 10px;">Your cart total is <span style="color:#f64c3f">{{ cart.total_price | money }}</span>. You qualify for free shipping!</div>

<div id="nofreeship" style="font-weight:bold; padding: 10px;">Your cart total is <span style="color:#f64c3f">{{ cart.total_price | money }}</span>.<br>Spend {{ 2500 | minus: cart.total_price | money }} more to qualify for free shipping!</div>
<script>
          !function checkprice() {
            var y = "2600" ;
            var x = "{{ cart.total_price }}";
          if (Number(x) > Number(y)) {
               document.getElementById("freeship").style.display = "block"; 
               document.getElementById("nofreeship").style.display = "none";
          } else {
               document.getElementById("freeship").style.display = "none";    
               document.getElementById("nofreeship").style.display = "block";     
          }

          } ();

</script>

UPDATE: Ryan, this is what I managed to dig up, I am guessing this is the code that updates the minicart at the top when an item is added to cart?

 function checkprice() {
                var baseprice = "2500" ;
                var carttotal = "{{ cart.total_price }}";
              if (Number(carttotal) > Number(baseprice) {
  document.getElementById("freeship").style.display = "none";
                document.getElementById("nofreeship").style.display = "block";
              } else {
  document.getElementById("freeship").style.display = "block";
                document.getElementById("nofreeship").style.display = "none";

              }

              };

ProductView.prototype.updateMiniCart = function(cart) {
    var i, item, itemProperties, itemText, j, len, miniCartItemsWrap, productPrice, propertiesArray, propertyKeysArray, ref, variant;
    miniCartItemsWrap = $(".mini-cart-items-wrap");
    miniCartItemsWrap.empty();
    if (cart.item_count !== 1) {
      itemText = Theme.cartItemsOther;
    } else {
      itemText = Theme.cartItemsOne;
      $(".mini-cart .options").show();
      miniCartItemsWrap.find(".no-items").hide();
    }
    $(".mini-cart-wrap label").html("<span class='item-count'>" + cart.item_count + "</span> " + itemText);
    ref = cart.items;
    for (j = 0, len = ref.length; j < len; j++) {
      item = ref[j];
      productPrice = Shopify.formatMoney(item.line_price, Theme.moneyFormat);
      variant = item.variant_title ? "<p class='variant'>" + item.variant_title + "</p>" : "";
      itemProperties = "";
      if (item.properties) {
        propertyKeysArray = Object.keys(item.properties);
        propertiesArray = _.values(item.properties);
        i = 0;
        while (i < propertyKeysArray.length) {
          if (propertiesArray[i].length) {
            itemProperties = itemProperties + ("<p class=\"property\">\n    <span class=\"property-label\">" + propertyKeysArray[i] + ":</span>\n    <span class=\"property-value\">" + propertiesArray[i] + "</span>\n</p>");
          }
          i++;
        }
      }
      miniCartItemsWrap.append("<div id=\"item-" + item.variant_id + "\" class=\"item clearfix\">\n    <div class=\"image-wrap\">\n        <img alt=\"" + item.title + "\" src=\"" + item.image + "\">\n        <a class=\"overlay\" href=\"" + item.url + "\"></a>\n    </div>\n    <div class=\"details\">\n        <p class=\"brand\">" + item.vendor + "</p>\n        <p class=\"title\"><a href=\"" + item.url + "\">" + item.product_title + "</a><span class=\"quantity\">× <span class=\"count\">" + item.quantity + "</span></span></p>\n        <p class=\"price\"><span class=\"money\">" + productPrice + "</span></p>\n        " + variant + "\n        " + itemProperties + "\n    </div>\n</div>");
    };checkprice()

    if (Theme.currencySwitcher) {
      return $(document.body).trigger("switch-currency");
    }
  };
Kelvin Lee
  • 13
  • 1
  • 5
  • 1
    This function runs once on page load, that is why the user has to refresh the page to see the change. You could add an `event handler` to the shopping cart so that it calls this function when an item is added or removed. If you can post the HTML for your shopping cart or any relevant code for adding or removing an item we can help you more. As far as the `!function` in the code, this post explains what the programmer was doing (https://stackoverflow.com/questions/3755606/what-does-the-exclamation-mark-do-before-the-function) – Ryan Wilson Jan 11 '19 at 13:36
  • Hi @Ryan Wilson, thank you for your quick reply! I am the "programmer", the code is just something I cobbled together, and I added the !function so on page load it would display properly. Like I said, I am terribly new to this, so can you point me to what I sould be looking out for when you say the HTML to my shopping cart? I am also assuming that the {{ cart.total_price | money }} will be an issue because that will not load properly when I refresh the without reloading the page, am I right? – Kelvin Lee Jan 11 '19 at 13:58
  • I meant the element inside the page which represents your shopping cart if it is some kind of image or something, but that may not really matter, the more important piece is the code you are using to add or remove an item from the shopping cart. – Ryan Wilson Jan 11 '19 at 14:01
  • Ok I have dug up something which I think might be what you want. Please do let me know if it is not the right one! – Kelvin Lee Jan 11 '19 at 14:11
  • You can try adding `checkprice();` right before this line `if (Theme.currencySwitcher) { return $(document.body).trigger("switch-currency"); }` in your new post. As I'm not sure if the variable `cart.total_price` will be up to date or not at that point, if not, you may need to add to `cart.total_price` on the iteration of the for loop to add each item's cost to the total, but theoretically, if `cart.total_price` is up to date at the end of the loop, calling `checkprice()` at that point should give you the desired results without having to refresh. – Ryan Wilson Jan 11 '19 at 14:22
  • Hi Ryan, I have uploaded the edited code above, I set everything as display:none just to test if it works, but nothing is happening :( – Kelvin Lee Jan 11 '19 at 16:11
  • Don't re-declare the function `checkprice`(), just call it with this line of code `checkprice();` Replace all of this `function checkprice() {var y = "2500" ; var x = "{{ cart.total_price }}"; if (Number(x) > Number(y)) { document.getElementById("freeship").style.display = "block"; document.getElementById("nofreeship").style.display = "none"; } else { document.getElementById("freeship").style.display = "none"; document.getElementById("nofreeship").style.display = "none";}}` with just `checkprice();` in your updated code. – Ryan Wilson Jan 11 '19 at 16:40
  • the function `checkprice()` is already defined in your script tag – Ryan Wilson Jan 11 '19 at 16:43
  • Hey Ryan, it works now, but now I have the problem of {{ cart.total_price }} not refreshing, and also as a result it does not work in the function because {{ cart.total_price }} is not being rendered as a number. How can I get the page to refresh this number? – Kelvin Lee Jan 11 '19 at 17:16
  • You would need to replace the value in the span with the updated value, by setting it's `innerText` property, same for the other by converting it to an integer, you can use the `parseInt` or `parseFloat` functions to turn text into numbers. Can you please update your post to what you are doing now with your code so I can see if there are any issues. – Ryan Wilson Jan 11 '19 at 17:19
  • Hi Ryan, I have updated my code. I needed to define the function again, or it would throw me an error saying function is not defined. I'm sorry but what you just mentioned sounds a little greek to me, like I said I am not very good at this, thank you for helping me so far! The problem is I cannot just replace the span with {{ cart.total_price }} too, because that is a shopify liquid variable, and I think it is parsed before the page even loads. – Kelvin Lee Jan 11 '19 at 17:49
  • I added an answer below to help with the next part, this is getting to be too much to type in comments, if that helps you achieve what you want, please mark it as the accepted answer, otherwise I will delete it if I need to continue assisting you. – Ryan Wilson Jan 11 '19 at 18:08

1 Answers1

0

HTML (Give the spans an id property):

<div id="freeship" style="font-weight:bold; padding: 10px;">Your cart total is <span style="color:#f64c3f" id="spnQualifyTotal">{{ cart.total_price | money }}</span>. You qualify for free shipping!</div>

<div id="nofreeship" style="font-weight:bold; padding: 10px;">Your cart total is <span style="color:#f64c3f" id="spnMoreTotal">{{ cart.total_price | money }}</span>.<br>Spend {{ 2500 | minus: cart.total_price | money }} more to qualify for free shipping!</div>

Javascript:

//Change this to take in the new total
function checkprice(total) {
                var baseprice = "2500" ;
                //Does this next line work???
                //var carttotal = "{{ cart.total_price }}"; Wont need this anymore
                //If so you can set the span's innerText to the new total
                document.getElementById('spnQualifyTotal').innerText = total;
                document.getElementById('spnMoreTotal').innerText = total;
              if (Number(total) > Number(baseprice)) {
  document.getElementById("freeship").style.display = "none";
                document.getElementById("nofreeship").style.display = "block";
              } else {
  document.getElementById("freeship").style.display = "block";
                document.getElementById("nofreeship").style.display = "none";

              }

              };

ProductView.prototype.updateMiniCart = function(cart) {
    var i, item, itemProperties, itemText, j, len, miniCartItemsWrap, 
    productPrice, propertiesArray, propertyKeysArray, ref, 
    variant, newTotal; //See the newTotal variable to get the total of all items in cart
    miniCartItemsWrap = $(".mini-cart-items-wrap");
    miniCartItemsWrap.empty();
    if (cart.item_count !== 1) {
      itemText = Theme.cartItemsOther;
    } else {
      itemText = Theme.cartItemsOne;
      $(".mini-cart .options").show();
      miniCartItemsWrap.find(".no-items").hide();
    }
    $(".mini-cart-wrap label").html("<span class='item-count'>" + cart.item_count + "</span> " + itemText);
    ref = cart.items;
    for (j = 0, len = ref.length; j < len; j++) {
      item = ref[j];
      productPrice = Shopify.formatMoney(item.line_price, Theme.moneyFormat);
      newTotal += item.line_price; //Adding each item's cost to the newTotal
      variant = item.variant_title ? "<p class='variant'>" + item.variant_title + "</p>" : "";
      itemProperties = "";
      if (item.properties) {
        propertyKeysArray = Object.keys(item.properties);
        propertiesArray = _.values(item.properties);
        i = 0;
        while (i < propertyKeysArray.length) {
          if (propertiesArray[i].length) {
            itemProperties = itemProperties + ("<p class=\"property\">\n    <span class=\"property-label\">" + propertyKeysArray[i] + ":</span>\n    <span class=\"property-value\">" + propertiesArray[i] + "</span>\n</p>");
          }
          i++;
        }
      }
      miniCartItemsWrap.append("<div id=\"item-" + item.variant_id + "\" class=\"item clearfix\">\n    <div class=\"image-wrap\">\n        <img alt=\"" + item.title + "\" src=\"" + item.image + "\">\n        <a class=\"overlay\" href=\"" + item.url + "\"></a>\n    </div>\n    <div class=\"details\">\n        <p class=\"brand\">" + item.vendor + "</p>\n        <p class=\"title\"><a href=\"" + item.url + "\">" + item.product_title + "</a><span class=\"quantity\">× <span class=\"count\">" + item.quantity + "</span></span></p>\n        <p class=\"price\"><span class=\"money\">" + productPrice + "</span></p>\n        " + variant + "\n        " + itemProperties + "\n    </div>\n</div>");
    };
    checkprice(newTotal); //Pass in the newTotal variable to checkprice(total);

    if (Theme.currencySwitcher) {
      return $(document.body).trigger("switch-currency");
    }
  };
Ryan Wilson
  • 10,223
  • 2
  • 21
  • 40
  • Thank you for this Ryan! Yes this will work perfectly, the line you mentioned does not work because it's a Shopify liquid variable, I will do some googling to see how I can update that variable. – Kelvin Lee Jan 11 '19 at 18:25
  • @KelvinLee I'm confused, in your one comment you said things were working, but you needed to update the spans, if it was working to determine whether to show the specific message for whether they got a rebate or what not, then how does this not work? – Ryan Wilson Jan 11 '19 at 18:29
  • Ryan, sorry for being unclear, the working part is the JS being called when an item is added to cart, but what is not working is the {{ cart.total_price }}, which when added via JS does nothing, because it will just show as {{ cart.total_price }}, instead of reflecting the actual current cart total. I suspect it is because Shopify converts all these variables into numbers only during page load, so adding them via JS after that does nothing. – Kelvin Lee Jan 11 '19 at 18:52
  • @KelvinLee That was what I was afraid of. You'll probably need to refer back to one of my previous comments, where you add each items price in the for loop, Ill update my answer – Ryan Wilson Jan 11 '19 at 18:56
  • @KelvinLee I updated my answer and left comments on the new stuff I added or changed. – Ryan Wilson Jan 11 '19 at 19:03
  • Hey Ryan, I plugged this in and 2 things happened: 1. Some parts of the site broke 2. When clicking on add to cart, it now redirects straight to the cart page. I checked for errors and saw a "Uncaught SyntaxError: Unexpected token {", and it was apparently referencing to the line: if (Number(total) > Number(baseprice) { I have no idea why because it looks correct to me, I'm gonna double-check to see if I have plugged it in wrongly. – Kelvin Lee Jan 11 '19 at 19:24
  • @KelvinLee This line `if (Number(total) > Number(baseprice)) {` in `function checkprice(total)` was missing the second closing parenthesis `)`, either I copied it wrong from your post or it was an error when posted. I updated my answer again. – Ryan Wilson Jan 11 '19 at 19:28
  • @KelvinLee Did you add the `id` properties to those span elements as I showed you in the `HTML` portion of my answer? – Ryan Wilson Jan 11 '19 at 19:30
  • Sorry I forgot about them! Placed them in now and the result is: Uncaught TypeError: document.getElementById(...).innerText is not a function Referencing: document.getElementById('spnQualifyTotal').innerText(total); – Kelvin Lee Jan 11 '19 at 19:33
  • @KelvinLee I goofed, you set `innerText` with the equal sign, I updated my answer again to reflect the correct way to set that property. – Ryan Wilson Jan 11 '19 at 19:34
  • We're getting close! The code works now, adding an item more than $25 switches the span to "freeship" properly too, but it now says : Your cart total is NaN. You qualify for free shipping! And another thing, when I added a $24.99 product, it still switched and said I qualified for free shipping. – Kelvin Lee Jan 11 '19 at 19:41
  • @KelvinLee `Nan` stands for `not a number`, are you able to see what the value of `total` is? – Ryan Wilson Jan 11 '19 at 19:44
  • I'm trying to but reading your code has left me bewildered! My knowledge of JS is very limited, I'm not even sure where the value of total is pulled from :( – Kelvin Lee Jan 11 '19 at 19:51
  • The value of total is passed into the function `checkprice` inside of the `updateminicart` function, it's name is `newTotal` inside of there, but it is what is passed to `checkprice` as `total`. Do you know how to use the developer tools in your browser to set a breakpoint in the code? – Ryan Wilson Jan 11 '19 at 19:58
  • @KelvinLee I just tried that and was unable to locate the javascript file – Ryan Wilson Jan 11 '19 at 20:36
  • @KelvinLee Inside of `checkprice(total)` add this line `alert(total);` at the beginning of the function, it should show in an alert message what the value of total is. So place it before `var baseprice = "2500";` – Ryan Wilson Jan 11 '19 at 20:44
  • Ok please give me a while, I have added it, and am trying to find where the alert is. I'm a little lost! EDIT: Ok i checked, the alert says NaN too. – Kelvin Lee Jan 11 '19 at 21:06
  • @KelvinLee I'm not sure how you ended up having to do the coding but you may want to see about finding a web developer to assist in your work. – Ryan Wilson Jan 11 '19 at 21:08
  • I understand, I am just trying to do everything myself, and while I haven't had any official training, I just learn bits and pieces on the internet and do copy and pasting. Thank you so much for your help anyways! I really appreciate it. – Kelvin Lee Jan 11 '19 at 21:15
  • @KelvinLee While it's admirable that you want to learn, this is a large project and trying to do it all yourself without having a good understanding of programming might be more trouble than you are bargaining for. Good luck to you. – Ryan Wilson Jan 11 '19 at 21:20
  • Ryan, I read your comments over and over again, and finally realised that what you were trying to do was to add the current products price into the total, so I figured that Shopify should have a variable for cart total, and with a little bit of digging, I found it! I updated your code and it works perfectly now. Just left with switching the displayed number to $xx.xx format and I am done. Thank you so much for your help, you have been invaluable and a great person! – Kelvin Lee Jan 11 '19 at 21:59
  • @kelvinlee I'm happy I could help, in your post may lie the answer, Shopify.formatMoney – Ryan Wilson Jan 12 '19 at 00:45