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:live_rate_shipping_modification [2016/06/16 07:26] – [Step 2: Add Javascript] adamv:2.0:snippets:live_rate_shipping_modification [2018/09/17 13:17] (current) – [Live Rate Shipping Modification] adam
Line 1: Line 1:
 ====== Live Rate Shipping Modification  ====== ====== Live Rate Shipping Modification  ======
 +<WRAP center round important 90%>
 +**This snippet has been replaced.** In place of the following snippet, we now have [[v:2.0:shipping:custom_code|a custom shipping code]] feature in FoxyCart 2.0 that allows you to modify returned live rates and provide custom rates to your customers without needing to add extra javascript to change the way the checkout works. **Please use [[v:2.0:shipping:custom_code|the new custom shipping code functionality]] instead of this snippet.** [[v:2.0:shipping:custom_code:migrating|Review this page for notes]] on migrating to the new functionality. This page will remain for reference.</WRAP>
 +
 <WRAP center round important 80%> <WRAP center round important 80%>
 **Test!** The following code is new, and while it has been tested in specific scenarios, there may be bugs or issues present. Ensure that you test thoroughly within your set up. **Test!** The following code is new, and while it has been tested in specific scenarios, there may be bugs or issues present. Ensure that you test thoroughly within your set up.
Line 9: Line 12:
  
  
-The following functionality allows you to add, update and remove any number of live rate shipping options based on any criteria (eg: what categories are products in, total cost of the cart, shipping destination country). <wrap hi>This script is limited to live rate shipping only.</wrap>+The following functionality allows you to add, update and remove any number of live rate shipping options based on various criteria (eg: what categories are products in, total cost of the cart, shipping destination country). <wrap hi>This script is limited to live rate shipping only.</wrap>
  
 <wrap important>The functionality described on this page require advanced javascript knowledge, and are not officially supported.</wrap> They are included in our official wiki because certain shipping methods and functionality are not natively supported, and though we are working on radically improving our shipping functionality, in the meantime these methods may be great workarounds. Use with caution, test, and post in [[http://forum.foxycart.com/|our forum]] if you run into problems. <wrap important>The functionality described on this page require advanced javascript knowledge, and are not officially supported.</wrap> They are included in our official wiki because certain shipping methods and functionality are not natively supported, and though we are working on radically improving our shipping functionality, in the meantime these methods may be great workarounds. Use with caution, test, and post in [[http://forum.foxycart.com/|our forum]] if you run into problems.
Line 19: Line 22:
  
 Update categories to 'Shipped using live rates' and select at least one live rate option from the 'shipping' page. Update categories to 'Shipped using live rates' and select at least one live rate option from the 'shipping' page.
-===== Step 2: Add Javascript =====+ 
 +===== Step 2: Disable Shipping Rate Signing ===== 
 +If you're planning to add new custom rates, or modify the returned rates in any way (such as altering the price or changing the labels), you will need to ensure that shipping rate signing is disabled for your store. If you just plan to hide/show the returned rates, you can skip this step. 
 + 
 +To disable shipping rate signing, head to the “shipping” section of your store's FoxyCart administration, and at the bottom of the page ensure that “enable shipping rate signing” is disabled. 
 + 
 +===== Step 3: Add Javascript =====
  
 Add the following to the "custom footer" field of the "Add custom header and footer code to your templates" section in your store's FoxyCart administration, in TEMPLATES » configuration: Add the following to the "custom footer" field of the "Add custom header and footer code to your templates" section in your store's FoxyCart administration, in TEMPLATES » configuration:
Line 35: Line 44:
     /* BEGIN CUSTOM SHIPPING LOGIC */     /* BEGIN CUSTOM SHIPPING LOGIC */
  
-    +        
  
     /* END CUSTOM SHIPPING LOGIC */     /* END CUSTOM SHIPPING LOGIC */
     };     };
  
-    /* Live Rate Shipping Modification Logic v2.0.12 */ +    /* Live Rate Shipping Modification Logic v2.0.16 */ 
-    FC.customLiveShipping.add=function(a,b,c,d){FC.json.shipping_address.shipping_results.push({method:c,price:b,service_id:a,service_name:d})};FC.customLiveShipping.hide=function(a){a=FC.customLiveShipping.filterShippingOptions(a);for(var b=0;b<a.length;b++)FC.json.shipping_address.shipping_results[a[b]].hide=!0};FC.customLiveShipping.show=function(a){a=FC.customLiveShipping.filterShippingOptions(a);for(var b=0;b<a.length;b++)FC.json.shipping_address.shipping_results[a[b]].hide=!1}; +    FC.customLiveShipping.add=function(a,d,c,b){FC.json.shipping_address.shipping_results.push({method:c,price:d,service_id:a,service_name:b})};FC.customLiveShipping.hide=function(a){a=FC.customLiveShipping.filterShippingOptions(a);for(var d=0;d<a.length;d++)FC.json.shipping_address.shipping_results[a[d]].hide=!0};FC.customLiveShipping.show=function(a){a=FC.customLiveShipping.filterShippingOptions(a);for(var d=0;d<a.length;d++)FC.json.shipping_address.shipping_results[a[d]].hide=!1}; 
-    FC.customLiveShipping.update=function(a,b,c,d){a=FC.customLiveShipping.filterShippingOptions(a);for(var e=0;e<a.length;e++){if("number"===typeof b||"string"===typeof b&&""!==b){var f=FC.customLiveShipping.modifyPrice(FC.json.shipping_address.shipping_results[a[e]].price,b);FC.json.shipping_address.shipping_results[a[e]].price=f}"string"===typeof c&&(FC.json.shipping_address.shipping_results[a[e]].method=c);"string"===typeof d&&(FC.json.shipping_address.shipping_results[a[e]].service_name=d)}}; +    FC.customLiveShipping.update=function(a,d,c,b){a=FC.customLiveShipping.filterShippingOptions(a);for(var e=0;e<a.length;e++){if("number"===typeof d||"string"===typeof d&&""!==d){var f=FC.customLiveShipping.modifyPrice(FC.json.shipping_address.shipping_results[a[e]].price,d);FC.json.shipping_address.shipping_results[a[e]].price=f}"string"===typeof c&&(FC.json.shipping_address.shipping_results[a[e]].method=c);"string"===typeof b&&(FC.json.shipping_address.shipping_results[a[e]].service_name=b)}}; 
-    FC.customLiveShipping.remove=function(a){FC.customLiveShipping.hide(a)};FC.customLiveShipping.reset=function(){FC.util.addressHasLocationInfo(FC.json.shipping_address)&&(0<FC.json.shipping_address.shipping_results.length&&delete FC.json.shipping_address.shipping_results[0].customLiveShippingHash,FC.cart.showShippingLocationInput(),FC[FC.json.context].getShippingOptions({address:FC.json.shipping_address}))};function customLiveShippingHandler(){FC.customLiveShipping.execute()} +    FC.customLiveShipping.remove=function(a){FC.customLiveShipping.hide(a)};FC.customLiveShipping.reset=function(){FC.util.addressHasLocationInfo(FC.json.shipping_address)&&(0<FC.json.shipping_address.shipping_results.length&&(FC.customLiveShipping.ratesHash=""),FC.customLiveShipping.shipping_service_id=FC.json.shipping_address.shipping_service_id,FC.cart.showShippingLocationInput(),FC[FC.json.context].getShippingOptions({address:FC.json.shipping_address}))}; 
-    function customCouponHandler(){FC.customLiveShipping.reset()} +    function customLiveShippingHandler(){FC.customLiveShipping.execute()}function customCouponHandler(){FC.customLiveShipping.reset()} 
-    FC.customLiveShipping.execute=function(){if(0<FC.json.shipping_address.shipping_results.length&&!FC.json.shipping_address.shipping_results[0].hasOwnProperty("customLiveShippingHash")){FC.customLiveShipping.logic(FC.json.shipping_address);for(var a=!1,b=FC.json.shipping_address.shipping_results.length-1;0<=b;b--)FC.json.shipping_address.shipping_results[b].hide?FC.json.shipping_address.shipping_results.splice(b,1):FC.json.shipping_address.shipping_results[b].service_id==FC.json.shipping_address.shipping_service_id&& +    FC.customLiveShipping.execute=function(){if(0<FC.json.shipping_address.shipping_results.length&&FC.customLiveShipping.hasChanged()){for(var a=[],d=[],c=!1,b=0;b<FC.json.shipping_address.shipping_results.length;b++)-1==a.indexOf(FC.json.shipping_address.shipping_results[b].service_id)?(a.push(FC.json.shipping_address.shipping_results[b].service_id),d.push(FC.json.shipping_address.shipping_results[b])):c=!0;c&&(FC.json.shipping_address.shipping_results=d);FC.customLiveShipping.logic(FC.json.shipping_address); 
-    (a=!0);a||(FC.json.shipping_address.shipping_service_description="",FC.json.shipping_address.shipping_service_id=0);FC.json.shipping_address.shipping_results.sort(function(a,b){return a.price-b.price});FC.customLiveShipping.config.autoSelect&&0==FC.json.shipping_address.shipping_service_id&&(FC.json.shipping_address.shipping_service_id=FC.json.shipping_address.shipping_results[0].service_id,FC.json.show_shipping_tbd=!1);FC.Template(FC.json.context).clearOutput();FC.cart.recalculateCartTotals();FC[FC.json.context].renderShippingRates(FC.json.shipping_address); +    FC.customLiveShipping.hasOwnProperty("shipping_service_id")&&0==FC.json.shipping_address.shipping_service_id&&(FC.json.shipping_address.shipping_service_id=FC.customLiveShipping.shipping_service_id);a=!1;for(b=FC.json.shipping_address.shipping_results.length-1;0<=b;b--)FC.json.shipping_address.shipping_results[b].hide?FC.json.shipping_address.shipping_results.splice(b,1):FC.json.shipping_address.shipping_results[b].service_id==FC.json.shipping_address.shipping_service_id&&(a=!0);a||(FC.json.shipping_address.shipping_service_description= 
-    0<FC.json.shipping_address.shipping_service_id&&jQuery("#shipping_service_id_"+FC.json.shipping_address.shipping_service_id).trigger("click.fc");FC.json.shipping_address.shipping_results[0].customLiveShippingHash=FC.util.hashString(JSON.stringify(FC.json.shipping_address.shipping_results))}}; +    "",FC.json.shipping_address.shipping_service_id=0);FC.json.shipping_address.shipping_results.sort(function(a,b){return a.price-b.price});FC.customLiveShipping.config.autoSelect&&0==FC.json.shipping_address.shipping_service_id&&(FC.json.shipping_address.shipping_service_id=FC.json.shipping_address.shipping_results[0].service_id,FC.json.show_shipping_tbd=!1);FC.Template(FC.json.context).clearOutput();FC.cart.recalculateCartTotals();FC[FC.json.context].renderShippingRates(FC.json.shipping_address);0< 
-    FC.customLiveShipping.filterShippingOptions=function(a){if("number"==typeof a){for(var b=[],c=0;c<FC.json.shipping_address.shipping_results.length;c++)FC.json.shipping_address.shipping_results[c].service_id==a&&(b=[c]);return b}if("string"==typeof a){for(var b=[],d={},c=0;c<FC.json.shipping_address.shipping_results.length;c++){var e=FC.json.shipping_address.shipping_results[c];d[c]=e.method+" "+e.service_name}if("all"!=a.toLowerCase()){a=/(fedex|usps|ups)?\s?([\w\s]+)?/i.exec(a);if(void 0==a||""== +    FC.json.shipping_address.shipping_service_id&&jQuery("#shipping_service_id_"+FC.json.shipping_address.shipping_service_id).trigger("click.fc");FC.customLiveShipping.ratesHash=FC.util.hashString(JSON.stringify(FC.json.shipping_address.shipping_results))}delete FC.customLiveShipping.shipping_service_id}; 
-    a)return;for(c in d)void 0!=a[1]&&""!=a[1]&&-1==d[c].toLowerCase().indexOf(a[1].toLowerCase())?delete d[c]:void 0!=a[2]&&""!=a[2]&&-1==d[c].toLowerCase().indexOf(a[2].toLowerCase())&&delete d[c]}for(c in d)b.push(parseInt(c));return b}if("object"==typeof a){b=[];for(c=0;c<a.length;c++)for(d=0;d<FC.json.shipping_address.shipping_results.length;d++)FC.json.shipping_address.shipping_results[d].service_id==a[c]&&b.push(d);return b}}; +    FC.customLiveShipping.hasChanged=function(){return FC.customLiveShipping.hasOwnProperty("ratesHash")&&""!=FC.customLiveShipping.ratesHash?FC.customLiveShipping.ratesHash!=FC.util.hashString(JSON.stringify(FC.json.shipping_address.shipping_results))?!0:!1:!0}; 
-    FC.customLiveShipping.modifyPrice=function(a,b){b=b.toString();var c=/([\+\-\=\*\/])?(\d+(?:\.\d+)?)(\%)?/.exec(b);a=parseFloat(a);var d=parseFloat(c[2]);void 0!=c[3]&&""!=c[3]&&(d=d/100*a);switch(void 0==c[1]&&""!=c[1]?"=":c[1]){case "+":a+=d;break;case "-":a-=d;break;case "/":a/=d;break;case "*":a*=d;break;default:a=d}return 0>a?0:a};+    FC.customLiveShipping.filterShippingOptions=function(a){if("number"==typeof a){for(var d=[],c=0;c<FC.json.shipping_address.shipping_results.length;c++)FC.json.shipping_address.shipping_results[c].service_id==a&&(d=[c]);return d}if("string"==typeof a){d=[];var b={};for(c=0;c<FC.json.shipping_address.shipping_results.length;c++){var e=FC.json.shipping_address.shipping_results[c];b[c]=e.method+" "+e.service_name}if("all"!=a.toLowerCase()){a=/(fedex|usps|ups)?\s?(.+)?/i.exec(a);if(void 0==a||""==a)return; 
 +    for(c in b)void 0!=a[1]&&""!=a[1]&&-1==b[c].toLowerCase().indexOf(a[1].toLowerCase())?delete b[c]:void 0!=a[2]&&""!=a[2]&&-1==b[c].toLowerCase().indexOf(a[2].toLowerCase())&&delete b[c]}for(c in b)d.push(parseInt(c));return d}if("object"==typeof a){d=[];for(c=0;c<a.length;c++)for(b=0;b<FC.json.shipping_address.shipping_results.length;b++)FC.json.shipping_address.shipping_results[b].service_id==a[c]&&d.push(b);return d}}; 
 +    FC.customLiveShipping.modifyPrice=function(a,d){d=d.toString();var c=/([\+\-=\*\/])?(\d+(?:\.\d+)?)(%)?/.exec(d);a=parseFloat(a);var b=parseFloat(c[2]);void 0!=c[3]&&""!=c[3]&&(b=b/100*a);switch(void 0==c[1]&&""!=c[1]?"=":c[1]){case "+":a+=b;break;case "-":a-=b;break;case "/":a/=b;break;case "*":a*=b;break;default:a=b}return 0>a?0:a};
     FC.client.on("cart-coupon-add.done",customCouponHandler);FC.client.on("cart-coupon-remove.done",customCouponHandler);     FC.client.on("cart-coupon-add.done",customCouponHandler);FC.client.on("cart-coupon-remove.done",customCouponHandler);
     {% if context == "cart" and not cart_is_fullpage %}     {% if context == "cart" and not cart_is_fullpage %}
         FC.client.on("cart-shipping-options-update.done",customLiveShippingHandler);FC.customLiveShipping.reset();         FC.client.on("cart-shipping-options-update.done",customLiveShippingHandler);FC.customLiveShipping.reset();
     {% else %}     {% else %}
-        $(document).ajaxComplete(function(b,c,a){b=/ThisAction=(\w+)/;c="";void 0!==a&&a.hasOwnProperty("url")&&-1!=a.url.search(b)&&(c=a.url.match(b)[1]);"GetShippingCost"==c&&FC.customLiveShipping.execute()});FC.client.on("customer-login.done",FC.customLiveShipping.reset);FC.client.on("ready.done",FC.customLiveShipping.reset);+        $(document).ajaxComplete(function(b,c,a){b=/ThisAction=(\w+)/;void 0!==a&&a.hasOwnProperty("url")&&-1!=a.url.search(b)&&a.url.match(b);FC.customLiveShipping.execute()});FC.client.on("customer-login.done",FC.customLiveShipping.reset);FC.client.on("ready.done",FC.customLiveShipping.reset); 
 +        if("required"==FC.json.config.template_config.analytics_config.google_analytics.usage)FC.client.on("checkout-submit",function(b,a){setTimeout(a,500)});
     {% endif %}     {% endif %}
 })(FC, jQuery); })(FC, jQuery);
 </script> </script>
-{% endif %} </code>+{% endif %}</code>
  
 Alternatively you can also add this code right at the end of the ''cart include'' template (not the ''cart'' or ''checkout'' templates, the ''cart include'' template will include it there for you). Alternatively you can also add this code right at the end of the ''cart include'' template (not the ''cart'' or ''checkout'' templates, the ''cart include'' template will include it there for you).
Line 66: Line 78:
 If you have created your own cart or checkout templates, ensure you've followed the steps to include the custom code placeholders as [[https://wiki.foxycart.com/v/2.0/templates/intermediate-automagicache#include_custom_code_placeholders|detailed here]] If you have created your own cart or checkout templates, ensure you've followed the steps to include the custom code placeholders as [[https://wiki.foxycart.com/v/2.0/templates/intermediate-automagicache#include_custom_code_placeholders|detailed here]]
 </WRAP> </WRAP>
-===== Step 3: Update Configuration =====+===== Step 4: Update Configuration =====
  
-This script currently provides a single option to alter the way the script works, present at the top of the javascript in step 2.+This script currently provides a single option to alter the way the script works, present at the top of the javascript in step 3.
  
 <code javascript>FC.customLiveShipping.config = { <code javascript>FC.customLiveShipping.config = {
Line 76: Line 88:
   * ''autoSelect'': If set to true, the top option for rates will be automatically selected after your custom logic has run.   * ''autoSelect'': If set to true, the top option for rates will be automatically selected after your custom logic has run.
  
-===== Step 4: Customise Shipping Options =====+===== Step 5: Customise Shipping Options =====
  
 Now the fun part, based on whatever criteria you want, add in the different shipping options you require for your site. Add your custom code between the ''/* BEGIN CUSTOM SHIPPING LOGIC */'' and ''/* END CUSTOM SHIPPING LOGIC */'' lines in the first script block. There are six functions available to you. Now the fun part, based on whatever criteria you want, add in the different shipping options you require for your site. Add your custom code between the ''/* BEGIN CUSTOM SHIPPING LOGIC */'' and ''/* END CUSTOM SHIPPING LOGIC */'' lines in the first script block. There are six functions available to you.
Line 245: Line 257:
 === Example 3 === === Example 3 ===
  
-  - Allow free shipping only if a certain coupon code is present. In this case, a coupon that contains the words "free shipping" (case insensitive). +  - Allow free shipping only if a certain coupon code is present. In this case, a coupon whose name, not the code, contains the words "free shipping" (case insensitive)
-  - This assumes you've enabled the 'free ground shipping' custom rate in your store's "shipping" settings.+     * Note that while the coupon's name is "free shipping", it is activated by a code, which can be, for example, "FREE576". Here we are looking for the coupon //name// "free shipping", not the code "FREE576"
 +  - This assumes you've enabled the 'free ground shipping' custom rate in your store's "shipping" settings: Go to STORE » shipping, under the CUSTOM OPTIONS title check the "use custom:" box, then in the list of options that appears check the "free ground shipping" box. Click "Update".
  
 <code javascript> <code javascript>
Line 279: Line 292:
  FC.customLiveShipping.show('fedex');  FC.customLiveShipping.show('fedex');
 }</code> }</code>
 +
 +=== Example 6 ===
 +
 +  - If the total order is over $99, offer free shipping on the priority mail option (for both domestic and international orders). You'll need to have USPS priority mail option turned on in your shipping page of your store's FoxyCart administration.
 +  - Make sure ''"shipping rate signing"'' is turned off in your shipping page of your store's FoxyCart administration. The approach to include custom free shipping will not work with the rate signing functionality, so we need to turn that off in this instance.
 +  - If your cart contains a discount, the free shipping logic will be applied //after// the discount, so if the cart's original total is over $99, but a discount makes the total less than $99, the free shipping will not apply.
 +
 +<code javascript>
 +var eligible_amount = FC.json.total_item_price + FC.json.total_discount;
 +if (eligible_amount > 99) {
 +    FC.customLiveShipping.update('priority mail', 0);
 +}
 +</code>
 ===== Changelog ===== ===== Changelog =====
  
Line 293: Line 319:
   * 2016/01/09 - v2.0.10 - Fixed an issue with coupons on the checkout   * 2016/01/09 - v2.0.10 - Fixed an issue with coupons on the checkout
   * 2016/06/02 - v2.0.11 - Altered how the live rates logic hooks into the checkout events to make sure it only runs when it should.   * 2016/06/02 - v2.0.11 - Altered how the live rates logic hooks into the checkout events to make sure it only runs when it should.
 +  * 2016/06/16 - v2.0.12 - Ensure coupon changes trigger rate refresh on checkout
 +  * 2016/08/25 - v2.0.13 - Expanded the instances where the custom logic is attempted to be executed
 +  * 2016/09/29 - v2.0.14 - Corrected rate filter strings to support special characters
 +  * 2017/08/08 - v2.0.15 - Ensure custom rates are re-selected after a ''reset()'' call
 +  * 2018/02/17 - v2.0.16 - Ensuring rates are re-run correctly after checkout validation errors when Google Analytics is enabled

Site Tools