Ratio calculator - js error

Highlighted
Shopify Partner
5 0 0

I have a javascript that is throwing an error on my page.

The way this ratio calculator is supposed to work, is that as soon as one input item is entered, the rest automatically populate

It looks like the javascript is not reading the "ratio" property correctly. 

 

Here is my page: https://white-rock-coffee-2.myshopify.com/pages/coffee-water-ratio

 

I feel like there is one tiny element that I am missing. Any help is much appreciated!

0 Likes
Shopify Partner
1843 172 543

Hi!

 

In your getValues function you aren't getting the DOM elements correctly.

 

For instance, instead of

document.table.brew.value

You should

document.getElementById('brew').value

Didn't look further beyond that error. Fix, try, rinse and repeat - a developers bread & butter ;-)

 

p.s. Is there a reason you aren't using jQuery since you already have it for your theme and it would make much of the code simpler and probably less brittle? Not that you have to, vanilla JS is also great, but usually preferred by purists.

 

Best wishes!

I turn coffee in to code - since 1998
0 Likes
Shopify Partner
1843 172 543

Speaking of coffee... time to get some! ☕

I turn coffee in to code - since 1998
0 Likes
Shopify Partner
5 0 0
Thank you KarlOffenberger
I was creating the calculator based off this codepen log:
https://codepen.io/anon/pen/ZVvbyO

This one seemed to work just fine, but it doesn't on my shopify site. I
thought there was a call mistake from what I coded. Will keep working on
it, any additional help is much appreciated!

0 Likes
Shopify Partner
1843 172 543

Programming is like magic. You write very specific instructions in arcane
languages to invoke commands, and if you get it even a little bit wrong
you risk unleashing demons and destroying everything - Diana Carrier

 

Or in other words copy paste and the myriad of examples, tutorials and forum posts, my own included, sometimes do unleash hell.

 

So is it working now? If not, feel free to ask.

I turn coffee in to code - since 1998
0 Likes
Shopify Partner
5 0 0
Nope its not. Can I pay you to fix it for me Karl? I have run out of time.
0 Likes
Shopify Partner
1843 172 543

Sorry to hear that you ran out of time. While I don't take on contract work currently, you can always take a look at and see if you find a suitable Shopify Expert.

 

I 💖 coffee. I mean I truly do. Travelled around Europe hunting for good roasts and cafes, events, etc. You know the slogan "But first coffee"!

 

So I thought it'd be fun to do this anyway especially because there are quite a few errors and no no's in what I've seen. Let me explain first:

 

  1. You're loading the form and script from a different website in to an iframe on your store. I'd generally not advise anyone to do that unless there's a good reason why they need to and they have obtained permission by the other site owners. Even so, it makes it difficult and often impossible to modify for your own needs which is what you'd want.
  2. The brew calculator from that other site is written in vanilla Javascript which is great and I prefer it that way, but Shopify themes almost always have jQuery laying around which also makes it simpler to read for beginners. The biggest issue though is that their calculator is written badly - change the values quickly by clicking through a spinner (the up down arrows on the number fields). Notice how it sometimes doesn't update the other fields until you move the mouse (blur the field)?
  3. As mentioned above, because you're loading in an iframe, you're loading a lot of other stuff you don't need - styles, html etc. It's unnecessary. They also use an entirely different CSS kit so the form looks out of place. In fact, not only that, it breaks mobile view if you check.

So let's fix that! (including rewrite to jQuery and the bugs they had in the original).

 

Ready? (grab a coffee... big mug)

 

Step 1

If you have a backup of your theme before you added that iframe and scripts for the calculator, revert to that version. If not, you will need to create a backup now so go to Online Store > Themes then Actions > Duplicate. Now start removing the iframe first, then any other scripts you've been adding. Try taking it step by step checking in between each step that nothing major breaks elsewhere. Once you're happy that the old calculator has been removed, backup again (important)!

 

p.s. if you only added the calculator by copy pasting in to the body field of your calculator page, awesome, that makes it easy to remove. But still create a backup of your theme before proceeding to Step 2.

 

Step 2

Go to Actions > Edit code and from the folder pane on the left, open the Templates folder. First link shows Add a new template so click that. In the popup you will want to choose "Create a new template for Page called calculator" and click Create template. You should now see an open file called page.calculator.liquid with some HTML in it similar to

 

<div class="page-width">
  <div class="grid">
    <div class="grid__item medium-up--five-sixths medium-up--push-one-twelfth">
      <div class="section-header text-center">
        <h1>{{ page.title }}</h1>
      </div>

      <div class="rte">
        {{ page.content }}
      </div>
    </div>
  </div>
</div>

Step 3

Go to your Pages and open the page for your calculator. Change the Template (bottom right column) to be Template suffix of page.calculator so we assign it the template code we created in the previous step. Save and return to your theme editor.

 

Step 4

Back in the editor and with the same page.calculator.liquid still open, you will want to add the custom form now. In my case, it's enough to simply paste it at the very end - however, you are using a custom or commercial theme so I cannot help you where to paste the code and how to apply CSS classes to spice it up with your theme looks.

 

<div class="page-width">
  <div class="grid">
    <div class="grid__item medium-up--five-sixths medium-up--push-one-twelfth">
      <form name="brewCalculator" id="BrewCalculator">
        <div class="grid">
          <div class="grid__item medium-up--one-half">
            <label for="Brew">Brew</label>
            <input type="number" id="Brew" name="brew" value="0">
            <select id="BrewWeight" name="brewWeight">
              <option id="ml" selected value="1">Milliliters</option>
              <option id="l" value="1000">Liter</option>
              <option id="g" value="3785.41">Gallons</option>
              <option id="c" value="236.588">Cups</option>
              <option id="oz" value="29.5735">Ounces</option>
            </select>
          </div>
          <div class="grid__item medium-up--one-half">
            <label for="Water">Water</label>
            <input type="number" id="Water" name="water" value="0">
            <select id="WaterWeight" name="waterWeight">
              <option id="ml" selected value="1">Milliliters</option>
              <option id="l" value="1000">Liter</option>
              <option id="g" value="3785.41">Gallons</option>
              <option id="c" value="236.588">Cups</option>
              <option id="oz" value="29.5735">Ounces</option>
            </select>
          </div>
          <div class="grid__item medium-up--one-half">
            <label for="Grounds">Grounds</label>
            <input type="number" id="Grounds" name="grounds" value="0">
            <select id="GroundsWeight" name="groundsWeight">
              <option id="g" selected value="1">Grams</option>
              <option id="oz" value="28.3527076">Ounces</option>
              <option id="tb" value="7.00035">Tablespoons</option>
            </select>
          </div>
          <div class="grid__item medium-up--one-half">
            <label for="Ratio">Ratio</label>
            <select id="Ratio" name="ratio">
              <option value="14">14:1</option>
              <option value="15">15:1</option>
              <option selected value="16">16:1 (default)</option>
              <option value="17">17:1</option>
              <option value="18">18:1</option>
            </select>
          </div>
        </div>
      </form>
    </div>
  </div>
</div>

<!--[if (gt IE 9)|!(IE)]><!--><script src="{{ 'calculator.js' | asset_url }}" defer="defer"></script><!--<![endif]-->
<!--[if lte IE 9]><script src="{{ 'calculator.js' | asset_url }}"></script><![endif]-->

Step 5

Now you need to create the actual JavaScript asset. Open the Assets folder and click on Add a new asset. Proceed as follows

 

0w7skgv

 

Step 6

Open the created file and paste this code inside

 

$(function() {
  var $lastSet = '';
  var $form = $('#BrewCalculator');
  var $brew = $('#Brew');
  var $water = $('#Water');
  var $grounds = $('#Grounds');
                
  var _objectify = function(array) {
    var o = {};
    for (var i = 0; i < array.length; i++){
      o[array[i]['name']] = parseFloat(array[i]['value']);
    }
    return o;
  }
  
  var _calculateBrewRatio = function(w, ww, g, gw, bw) {
    b = ((w*ww - 2*g*gw)/bw).toFixed(3);
    $brew.val(b);
  }

  var _calculateGroundsFromBrew = function(b, bw, gw, r) {
    g = (((b*bw)/(r - 2))/gw).toFixed(3);
    $grounds.val(g);
    return g;
  }

  var _calculateWaterRatio = function(g, gw, ww, r) {
    w = ((g * gw * r) / ww).toFixed(3);
    $water.val(w);
    return w;
  }

  var _calculateGroundsRatio = function(w, ww, r, gw) {
    g = (((w * ww) / (r * gw))).toFixed(3);
    $grounds.val(g);
    return g
  }
  
  var _calculate = function(field, data) {
    switch (field) {
      case 'brew':
        data.grounds = _calculateGroundsFromBrew(data.brew, data.brewWeight, data.groundsWeight, data.ratio);
        _calculateWaterRatio(data.grounds, data.groundsWeight, data.waterWeight, data.ratio);
        break;
      case 'water':
        data.grounds = _calculateGroundsRatio(data.water, data.waterWeight, data.ratio, data.groundsWeight);
        _calculateBrewRatio(data.water, data.waterWeight, data.grounds, data.groundsWeight, data.brewWeight);
        break;
      case 'grounds':
        data.water = _calculateWaterRatio(data.grounds, data.groundsWeight, data.waterWeight, data.ratio);
        _calculateBrewRatio(data.water, data.waterWeight, data.grounds, data.groundsWeight, data.brewWeight);
        break;
    }
  }
  
  $form.find(':input').on('change input', function() {
    var field = $(this)[0];
    if (field.type == 'number') {
      $lastSet = field.name;
    }
    var data =  _objectify($form.serializeArray());
    _calculate($lastSet, data);
  });
});

Save and give it a spin. If all worked well you should have a working calculator for making good coffee!

 

Step 7

HTML and styling to go together with your theme. That's up to you now 😀

 

Good luck and much success with your business!

 

I turn coffee in to code - since 1998
0 Likes
Shopify Partner
1843 172 543

p.s. added little bonus just in case you need to fiddle around with the calculator script, here it is on CodePen.

I turn coffee in to code - since 1998
0 Likes
Shopify Partner
5 0 0
Oh my! You are a rockstar and my caffeinated hero!
I followed your steps and reworked everything. And...it almost works. It
looks like there is something in my theme blocking the numbers from being
able to display the full length. It limits the field length to just the
number (1 digit); the javascript is showing ".toFixed(3);" so it should
have 3 digits after the decimal point...and the numbers are not auto
changing

In your codepen it has a long display box with the little arrows, and it
auto-changes when the one arrow is clicked.

It looks pretty though, the layout is set to the theme design (no grid,
o-layout)
https://white-rock-coffee-2.myshopify.com/pages/test

Thanks again for your help!
0 Likes
Shopify Partner
1843 172 543

Your inputs have a

pattern="[0-9]*"

That's a regex that limits your inputs to whole numbers only.

 

If you're not sure how to change that, I'll be available later tonight and can take a look.

I turn coffee in to code - since 1998
0 Likes