This is an old revision of the document!


Updating a total element to reflect selected price modifiers in your page

Step 1: Include jQuery

Firstly, ensure you're manually including jQuery on your page - and not relying on loader.js to include it for you. You can include it like this:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>

Step 2: Include snippet

Paste the following right after the jQuery include of any page that requires FoxyCart attribute modifiers calculations. This is *not* required on the cart or checkout pages, so should not be place in those templates.

<script type="text/javascript" charset="utf-8">
jQuery(document).ready(function() {
  TOTALCLASS = "_total";
  // Create an array to store all the adjustments
  ADJUST = [];
  // Set the handlers for each *_adjust form element
  $("[class$=_adjust]").each(function() {
    var pID = $(this).attr("class").split("_")[0];
    if (typeof(ADJUST[pID]) === "undefined") {
      // Create the array for this product code
      ADJUST[pID] = [];
    }
    switch(this.tagName) {
      case "SELECT":
        // Store the current value
        ADJUST[pID][$(this).attr("name")] = $(this).val();
        $(this).change(function() {
          var pID = $(this).attr("class").split("_")[0];
          ADJUST[pID][$(this).attr("name")] = $(this).val();
          recalcTotal();
        })
        break;
      case "INPUT":
        switch($(this).attr("type")) {
          case "checkbox":
            if ($(this).is(":checked")) {
                ADJUST[pID][$(this).attr("name")] = $(this).val();
              } else {
                ADJUST[pID][$(this).attr("name")] = "";
              }
            $(this).bind("change", function () {
              var pID = $(this).attr("class").split("_")[0];
              if ($(this).is(":checked")) {
                ADJUST[pID][$(this).attr("name")] = $(this).val();
              } else {
                ADJUST[pID][$(this).attr("name")] = "";
              }
              recalcTotal();
            })
            break;
          case "radio":
            // Store the current value
            if ($(this).is(":checked")) {
              ADJUST[pID][$(this).attr("name")] = $(this).val();
            }
 
            $(this).bind("change", function () {
              var pID = $(this).attr("class").split("_")[0];
              ADJUST[pID][$(this).attr("name")] = $(this).val();
              recalcTotal();
            })
            break;
        }
        break;
    }
  });
  recalcTotal();
});
var FC = FC || {};
FC.onLoad = function () {
  FC.client.on('ready.done', function () {
    recalcTotal();
  });
}
function parseAttributes(sValue) {
  sValue = sValue.match(/{(.*?)}/);
  if (sValue) {
    aValue = sValue[1].split("|");
    for(i in aValue) {
      aParts = aValue[i].match(/p([\+|\-|\:])(.+)/);
      if (aParts) {
        return aParts;
      }
    }
  }
  return;
}
function recalcTotal() {
  for(p in ADJUST) {
    price = Number($("#"+p+"_price").val());
    adjustment = 0;
    for (a in ADJUST[p]) {
      var aParts = parseAttributes(ADJUST[p][a]);
      if (aParts) {
        var modifier = aParts[1];
        switch(modifier) {
          case ":":
            price = Number(aParts[2]);
            break;
          case "+":
            adjustment += Number(aParts[2]);
            break;
          case "-":
            adjustment -= Number(aParts[2]);
            break;
        }
      }
    }
    price += adjustment;
    var fprice = (typeof FC == "object" && FC.hasOwnProperty("json") && FC.json.config.hasOwnProperty("currency_format")) ? FC.util.money_format(FC.json.config.currency_format, price) : price.formatMoney(2);
    $("."+p+TOTALCLASS).html(fprice);
  }
}
Number.prototype.formatMoney = function(c, d, t){
  var n = this, 
      c = isNaN(c = Math.abs(c)) ? 2 : c, 
      d = d == undefined ? "." : d, 
      t = t == undefined ? "," : t, 
      s = n < 0 ? "-" : "", 
      i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", 
      j = (j = i.length) > 3 ? j % 3 : 0;
  return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
};
</script>

Step 3: Set up forms

Setup your forms like so:

  • Every FoxyCart based product that have product modifiers needs to have a unique code set like:
 <input type="hidden" name="code" value="p1" /> 
  • Give your hidden price input an id that combines your code and “_price” like:
 <input type="hidden" name="price" id="p1_price" value="20" /> 
  • Any select, checkbox or radio element needs to be given a class that combines your code and “_adjust” like:

Selects:

 <select class="p1_adjust" name="Size">
<option value="10 ml">10 ml</option>
<option value="20 ml{c+test|p+2.50}">20 ml</option>
<option value="20 ml{p+50|c+test}">30 ml</option>
</select>

Checkboxes:

<label for="something">Something</label><input type="checkbox" name="something" value="Yes{p:10|c+test}" class="p1_adjust">

Radio Buttons (note that the grouped radio buttons need to all share the same “name”) :

<input type="radio" class="p1_adjust" name="group1" value="Milk{p:2}"><label>Milk</label>
<input type="radio" class="p1_adjust" name="group1" value="Butter{p:3}" checked><label>Butter</label>
<input type="radio" class="p1_adjust" name="group1" value="Cheese{p:4}"><label>Cheese</label>
  • Set an element to be where the total cost is shown and updated, by combining the code and “_total” as its class, like:
 <h4><span class="p1_total">$20.00</span></h4>

The total would be put into that span element, and as no dollar sign is returned with the value, that is placed outside the span in the h4 element. If you want to use a class that is the code combined with a different string, this can be set at the top of the javscript in the TOTALCLASS variable.

That's it!

That should be it. The script basically runs through all the elements that have a class ending in “_adjust”, and grabs what the active value is. If that value has a price modifier (p:X, p+X, p-X), it chucks it into an array. After looping over all the form elements, it loops through all the relevent price modifiers, and adjusts the base price and sets the total element. Worth noting is that if you have multiple flat price modifiers (eg p:30) where it alters the base price, only the last modifier is applied, but any plus or minus modifiers are applied after that.

Site Tools