This is an old revision of the document!
Table of Contents
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")) ? jQuery.trim(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.