Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
v:2.0:snippets:updating_total_price_with_option_modifers [2018/12/21 05:13] – [Total Price Element] adamv:2.0:snippets:updating_total_price_with_option_modifers [2023/07/12 10:38] (current) – [Dynamically triggering recalculation] adam
Line 10: Line 10:
 <code javascript> <code javascript>
 <script> <script>
-// Dynamic Price Calculation v3.1 +// Dynamic Price Calculation v3.3 
-var pricemod_regex=/[{\|]p([+\-:])([\d\.]+)(?:\D{3})?(?=[\|}])/,id_regex=/^(\d+):/,FC=FC||{};FC.onLoad=function(){FC.client.on("ready.done",initDynamicPrice)}; +var pricemod_regex=/[{\|]p([+\-:])([\d\.]+)(?:\D{3})?(?=[\|}])/,id_regex=/^(\d+):/,FC=FC||{};function initDynamicPrice(){ADJUST={},$("input,select").off("change.foxy-dynamic-price"),$('form[action*="'+FC.settings.storedomain+'"]').each((function(){var t=$(this),a="",e={products:{}};$(this).find("[name='name'],[name^='name||'],[name$=':name'],[name*=':name||']").each((function(){var r=getId(this.name),i=r?r+":":"",s=parseFloat(t.find("[name='"+i+"price'],[name^='"+i+"price||']").first().val()),c={id:r,code:"",base_price:isNaN(s)?0:s,quantity:1,attributes:{},has_quantity:!1},n=t.find("[name='"+i+"quantity'],[name^='"+i+"quantity||']"),o=t.find("[name='"+i+"code'],[name^='"+i+"code||']");if(o.length>0&&(c.code=clearHash(o.first().val()),""===a&&(a=c.code)),n.length>0){var d=0,h=getElementType(n);["select","text"].indexOf(h)>-1?(c.has_quantity=!0,d=parseFloat(clearHash(n.val()))):["radio","checkbox"].indexOf(h)>-1&&(c.has_quantity=!0,1==n.filter(":checked").length&&(d=parseFloat(clearHash(n.filter(":checked").val())))),isNaN(d)&&(d=0),c.quantity=d}e.products[r]=c}));t.attr("data-fc-form-code")&&(a=t.attr("data-fc-form-code")),""!==a&&($(this).find("input,select").each((function(){if(!this.disabled){var t=getId(this.name),r=getName(this.name),i=getElementType($(this));if("quantity"!=r)if("price"!=r||"hidden"==i){if("SELECT"==this.tagName){var s=!1;$(this).children("option").each((function(){this.value.search(pricemod_regex)>-1&&(s=!0)})),s&&($(this).data("fc-adjust-for",a),e.products[t].attributes[clearHash(this.name)]=clearHash(this.value),$(this).on("change.foxy-dynamic-price",(function(){ADJUST[$(this).data("fc-adjust-for")].products[t].attributes[clearHash(this.name)]=clearHash(this.value),recalcTotal()})))}else if(this.value.search(pricemod_regex)>-1)switch($(this).data("fc-adjust-for",a),$(this).attr("type")){case"checkbox":$(this).is(":checked")?e.products[t].attributes[clearHash(this.name)]=clearHash(this.value):e.products[t].attributes[clearHash(this.name)]="",$(this).on("change.foxy-dynamic-price",(function(){$(this).is(":checked")?ADJUST[$(this).data("fc-adjust-for")].products[t].attributes[clearHash(this.name)]=clearHash(this.value):ADJUST[$(this).data("fc-adjust-for")].products[t].attributes[clearHash(this.name)]="",recalcTotal()}));break;case"radio":e.products[t].attributes.hasOwnProperty(clearHash(this.name))||(e.products[t].attributes[clearHash(this.name)]=""),$(this).is(":checked")&&(e.products[t].attributes[clearHash(this.name)]=clearHash(this.value)),$("[name='"+this.name+"']").data("fc-adjust-for",a).on("change.foxy-dynamic-price",(function(){ADJUST[$(this).data("fc-adjust-for")].products[t].attributes[clearHash(this.name)]=clearHash(this.value),recalcTotal()}))}}else $(this).data("fc-adjust-for",a).on("change.foxy-dynamic-price",(function(){var a=0;(["select","text"].indexOf(i)>-1||["radio","checkbox"].indexOf(i)>-1&&$(this).is(":checked"))&&(a=parseFloat(clearHash(this.value))),isNaN(a)&&(a=0),ADJUST[$(this).data("fc-adjust-for")].products[t].base_price=a,recalcTotal()}));else $(this).data("fc-adjust-for",a).on("change.foxy-dynamic-price",(function(){var a=0;(["select","text"].indexOf(i)>-1||["radio","checkbox"].indexOf(i)>-1&&$(this).is(":checked"))&&(a=parseFloat(clearHash(this.value))),isNaN(a)&&(a=0),ADJUST[$(this).data("fc-adjust-for")].products[t].quantity=a,recalcTotal()}))}})),ADJUST[a]=e)})),recalcTotal()}function clearHash(t){return t.replace(/\|\|[\d\w]+(?:\|\|open)?$/,"")}function getNameParts(t){return(t=clearHash(t)).match(/(?:(\d+):)?(.*)/)}function getId(t){var a=getNameParts(t);return id_regex.test(this.name)&&(prefix=parseInt(this.name.match(id_regex)[0])),void 0===a[1]?0:parseInt(a[1])}function getName(t){return getNameParts(t)[2]}function getElementType(t){if("SELECT"==t[0].tagName)return"select";if("INPUT"==t[0].tagName)switch(t.attr("type").toLowerCase()){case"text":case"number":case"tel":return"text";default:return t.attr("type").toLowerCase()}}function recalcTotal(){for(f in ADJUST){var t=0,e=0;for(p in ADJUST[f].products){var r=ADJUST[f].products[p].base_price,i=0;for(a in ADJUST[f].products[p].attributes){var s=ADJUST[f].products[p].attributes[a].match(pricemod_regex);if(s)switch(s[1]){case":":r=parseFloat(s[2]);break;case"+":i+=parseFloat(s[2]);break;case"-":i-=parseFloat(s[2])}}r+=i,t+=r*=ADJUST[f].products[p].quantity,e+=ADJUST[f].products[p].quantity}"function"==typeof fcFormatPrice&&(t=fcFormatPrice(t,f)),"function"==typeof fcFormatQuantity&&(e=fcFormatQuantity(e,f)),t=adjustDisplayPrice(t);var c="object"==typeof FC&&FC.hasOwnProperty("json")&&FC.json.config.hasOwnProperty("currency_format")?jQuery.trim(FC.util.money_format(FC.json.config.currency_format,t)):t.formatMoney(2);$("."+f+"_total").html(c),$("."+f+"_total_quantity").html(e)}}function adjustDisplayPrice(t){return"function"!=typeof fc_adjust_price_display||(adjusted_price=fc_adjust_price_display(t),void 0===adjusted_price||isNaN(parseFloat(adjusted_price)))?t:parseFloat(adjusted_price)}FC.onLoad=function(){FC.client.on("ready.done",initDynamicPrice)},Number.prototype.formatMoney=function(t,a,e){var r=this,i=(t=isNaN(t=Math.abs(t))?2:t,a=null==a?".":a,e=null==e?",":e,r<0?"-":""),s=parseInt(r=Math.abs(+r||0).toFixed(t))+"",c=(c=s.length)>3?c%3:0;return i+(c?s.substr(0,c)+e:"")+s.substr(c).replace(/(\d{3})(?=\d)/g,"$1"+e)+(t?a+Math.abs(r-s).toFixed(t).slice(2):"")};
-function initDynamicPrice(){ADJUST={};$("input,select").off("change.foxy-dynamic-price");$('form[action*="'+FC.settings.storedomain+'"]').each(function(){var b=$(this),d="",g={products:{}};$(this).find("[name='name'],[name^='name||'],[name$=':name'],[name*=':name||']").each(function(){var k=getId(this.name),c=k?k+":":"",e=parseFloat(b.find("[name='"+c+"price'],[name^='"+c+"price||']").first().val());e={id:k,code:"",base_price:isNaN(e)?0:e,quantity:1,attributes:{},has_quantity:!1};var h=b.find("[name='"+ +
-c+"quantity'],[name^='"+c+"quantity||']");c=b.find("[name='"+c+"code'],[name^='"+c+"code||']");0<c.length&&(e.code=clearHash(c.first().val()),""===d&&(d=e.code));if(0<h.length){c=0;var l=getElementType(h);-1<["select","text"].indexOf(l)?(e.has_quantity=!0,c=parseFloat(clearHash(h.val()))):-1<["radio","checkbox"].indexOf(l)&&(e.has_quantity=!0,1==h.filter(":checked").length&&(c=parseFloat(clearHash(h.filter(":checked").val()))));isNaN(c)&&(c=0);e.quantity=c}g.products[k]=e});b.attr("data-fc-form-code")&& +
-(d=b.attr("data-fc-form-code"));""!==d&&($(this).find("input,select").each(function(){var b=getId(this.name),c=getName(this.name),e=getElementType($(this));if("quantity"==c)$(this).data("fc-adjust-for",d).on("change.foxy-dynamic-price",function(){var c=0;if(-1<["select","text"].indexOf(e)||-1<["radio","checkbox"].indexOf(e)&&$(this).is(":checked"))c=parseFloat(clearHash(this.value));isNaN(c)&&(c=0);ADJUST[$(this).data("fc-adjust-for")].products[b].quantity=c;recalcTotal()});else if("price"==c&&"hidden"!= +
-e)$(this).data("fc-adjust-for",d).on("change.foxy-dynamic-price",function(){var c=0;if(-1<["select","text"].indexOf(e)||-1<["radio","checkbox"].indexOf(e)&&$(this).is(":checked"))c=parseFloat(clearHash(this.value));isNaN(c)&&(c=0);ADJUST[$(this).data("fc-adjust-for")].products[b].base_price=c;recalcTotal()});else if("SELECT"==this.tagName){var h=!1;$(this).children("option").each(function(){-1<this.value.search(pricemod_regex)&&(h=!0)});h&&($(this).data("fc-adjust-for",d),g.products[b].attributes[clearHash(this.name)]= +
-clearHash(this.value),$(this).on("change.foxy-dynamic-price",function(){ADJUST[$(this).data("fc-adjust-for")].products[b].attributes[clearHash(this.name)]=clearHash(this.value);recalcTotal()}))}else if(-1<this.value.search(pricemod_regex))switch($(this).data("fc-adjust-for",d),$(this).attr("type")){case "checkbox":$(this).is(":checked")?g.products[b].attributes[clearHash(this.name)]=clearHash(this.value):g.products[b].attributes[clearHash(this.name)]="";$(this).on("change.foxy-dynamic-price",function(){$(this).is(":checked")? +
-ADJUST[$(this).data("fc-adjust-for")].products[b].attributes[clearHash(this.name)]=clearHash(this.value):ADJUST[$(this).data("fc-adjust-for")].products[b].attributes[clearHash(this.name)]="";recalcTotal()});break;case "radio":g.products[b].attributes.hasOwnProperty(clearHash(this.name))||(g.products[b].attributes[clearHash(this.name)]=""),$(this).is(":checked")&&(g.products[b].attributes[clearHash(this.name)]=clearHash(this.value)),$("[name='"+this.name+"']").data("fc-adjust-for",d).on("change.foxy-dynamic-price", +
-function(){ADJUST[$(this).data("fc-adjust-for")].products[b].attributes[clearHash(this.name)]=clearHash(this.value);recalcTotal()})}}),ADJUST[d]=g)});recalcTotal()}function clearHash(b){return b.replace(/\|\|[\d\w]+(?:\|\|open)?$/,"")}function getNameParts(b){b=clearHash(b);return b.match(/(?:(\d+):)?(.*)/)}function getId(b){b=getNameParts(b);id_regex.test(this.name)&&(prefix=parseInt(this.name.match(id_regex)[0]));return void 0===b[1]?0:parseInt(b[1])} +
-function getName(b){return getNameParts(b)[2]}function getElementType(b){if("SELECT"==b[0].tagName)return"select";if("INPUT"==b[0].tagName)switch(b.attr("type").toLowerCase()){case "text":case "number":case "tel":return"text";default:return b.attr("type").toLowerCase()}} +
-function recalcTotal(){for(f in ADJUST){var b=0,d=0;for(p in ADJUST[f].products){var g=ADJUST[f].products[p].base_price,k=0;for(a in ADJUST[f].products[p].attributes){var c=ADJUST[f].products[p].attributes[a].match(pricemod_regex);if(c)switch(c[1]){case ":":g=parseFloat(c[2]);break;case "+":k+=parseFloat(c[2]);break;case "-":k-=parseFloat(c[2])}}g+=k;g*=ADJUST[f].products[p].quantity;b+=g;d+=ADJUST[f].products[p].quantity}"function"===typeof fcFormatPrice&&(b=fcFormatPrice(b,f));"function"===typeof fcFormatQuantity&& +
-(d=fcFormatQuantity(d,f));b="object"==typeof FC&&FC.hasOwnProperty("json")&&FC.json.config.hasOwnProperty("currency_format")?jQuery.trim(FC.util.money_format(FC.json.config.currency_format,b)):b.formatMoney(2);$("."+f+"_total").html(b);$("."+f+"_total_quantity").html(d)}} +
-Number.prototype.formatMoney=function(b,d,g){var k=this;b=isNaN(b=Math.abs(b))?2:b;d=void 0==d?".":d;g=void 0==g?",":g;var c=0>k?"-":"",e=parseInt(k=Math.abs(+k||0).toFixed(b))+"",h=3<(h=e.length)?h%3:0;return c+(h?e.substr(0,h)+g:"")+e.substr(h).replace(/(\d{3})(?=\d)/g,"$1"+g)+(b?d+Math.abs(k-e).toFixed(b).slice(2):"")};+
 </script> </script>
 </code> </code>
Line 52: Line 41:
  
 <code javascript>initDynamicPrice();</code> <code javascript>initDynamicPrice();</code>
 +
 +==== Modify dynamically calculated total price ====
 +
 +If you need to dynamically modify the calculated price, for example if your product prices are tax exclusive, but you want to show the calculated price as tax inclusive, you can define a function on your page to achieve that result. The function has a name of ''fc_adjust_price_display'', and is passed a single argument which is the dynamically calculated total price. The function should return your modified price.
 +
 +As an example, let's say you want to account for a 25% inclusive tax on your product prices, that would look like this:
 +
 +<code javascript><script>
 +  function fc_adjust_price_display(price) {
 +    return price * 1.25;
 +  }
 +</script></code>
 ===== That's it! ===== ===== That's it! =====
  
-That should be it. The script basically runs through all the inputs within FoxyCart add to cart forms on the page, 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 selected price modifiers, adjusts the base price, multiplies it by the quantity and sets the total element.+That should be it. The script basically runs through all the inputs within FoxyCart add to cart forms on the page, 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 selected price modifiers, adjusts the base price, multiplies it by the quantity and sets the total element.
  
 ===== Notes and Limitations ===== ===== Notes and Limitations =====
  
   * The snippet is run after the FoxyCart javascript has been initialized. As such - there may be a small time while the page is loading before the dynamic total is calculated.   * The snippet is run after the FoxyCart javascript has been initialized. As such - there may be a small time while the page is loading before the dynamic total is calculated.

Site Tools