Table of Contents
Locations Modification
The following functionality adds some helper functions to your templates to allow you to dynamically restrict the countries and states that can be used by your customers to check out.
The functionality described on this page require advanced javascript knowledge, and are not officially supported. 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 our forum if you run into problems.
See the changelog for details on updates to this script.
Important note
Starting in 2.0, there is now a template configuration option to limit countries and states from right within your store's FoxyCart administration. This new option allows you to alter what locations are available for both the billing and shipping (either matching or independent of each other), without the need for the following snippet. You can access this feature from the “configuration” section under “templates”, look for “Customize allowlist/blocklist filtering of countries and regions”.
If you need to dynamically restrict the locations - for example, prevent orders from outside your country if perishable products are purchased, you can utilise the following script to do that. Otherwise, if your restrictions are static and don't depend on certain conditions being met, use the option in your store's admin.
Step 1: Add Javascript
Add the following in the “footer” section of the “Add custom header and footer code to your templates” option, found on the “configuration” page of your store's FoxyCart administration.
{% if context == 'cart' or context == 'checkout' %} <script type="text/javascript" charset="utf-8"> (function($, FC) { FC.locations.logic = function() { /* BEGIN CUSTOM LOCATION LOGIC */ /* END CUSTOM LOCATION LOGIC */ }; /* Country/State Helper Functions v2.2 */ FC.locations.removeCountries=function(a,b){if("undefined"==typeof a)return!1;"string"==typeof a&&(a=[a]);b=FC.locations.validateLocationArrayNames(b);for(l in b){0===FC.json.config["locations_"+b[l]].length&&(FC.json.config["locations_"+b[l]]={});for(var c in a)FC.json.config["locations_"+b[l]][a[c]]="*"}return!0}; FC.locations.limitCountriesTo=function(a,b){if("undefined"==typeof a)return!1;"string"==typeof a&&(a=[a]);b=FC.locations.validateLocationArrayNames(b);for(l in b){var c=FC.json.config.locations;FC.json.config["locations_"+b[l]]={};for(var d in c)-1==a.indexOf(d)&&(FC.json.config["locations_"+b[l]][d]="*")}return!0}; FC.locations.removeStates=function(a,b,c){if("undefined"==typeof a||"undefined"==typeof b)return!1;"string"==typeof b&&(b=[b]);c=FC.locations.validateLocationArrayNames(c);for(l in c){if("undefined"==typeof FC.json.config.locations[a])return!1;FC.json.config["locations_"+c[l]].hasOwnProperty(a)||(FC.json.config["locations_"+c[l]][a]=[]);for(var d in b)FC.json.config["locations_"+c[l]][a].push(b[d])}return!0}; FC.locations.limitStatesTo=function(a,b,c){if("undefined"==typeof a||"undefined"==typeof b)return!1;"string"==typeof b&&(b=[b]);c=FC.locations.validateLocationArrayNames(c);for(l in c){var d=FC.json.config.locations;if("undefined"==typeof d[a])return!1;FC.json.config["locations_"+c[l]][a]=[];for(var e in d[a].r.options)-1==jQuery.inArray(e,b)&&FC.json.config["locations_"+c[l]][a].push(e)}return!0}; FC.locations.validateLocationArrayNames=function(a){if("undefined"==typeof a||""==a||"both"==a)a=["billing","shipping"];"string"==typeof a&&(a=[a]);for(var b=0;b<a.length;b++)"customer"==a[b]&&(a[b]="billing");return a};FC.locations.reset=function(a){a=FC.locations.validateLocationArrayNames(a);for(l in a)FC.json.config["locations_"+a[l]]=FC.locations.hasOwnProperty("locations_"+a[l]+"_default")?FC.locations["locations_"+a[l]+"_default"]:{};customLocationsExecute()}; function customLocationsHandler(){FC.locations.hasOwnProperty("locations_billing_default")?FC.locations.reset():(FC.locations.locations_billing_default=FC.json.config.locations_billing,FC.locations.locations_shipping_default=FC.json.config.locations_shipping,customLocationsExecute())} function customLocationsExecute(){FC.locations.logic();FC.Template(FC.json.context).clearOutput();"cart"==FC.json.context?FC.cart.renderAddressEntry():(FC.checkout.renderCustomerBilling(),FC.checkout.renderCustomerShipping())}; {% if cart_is_fullpage or context == 'checkout' %}FC.client.on('ready', customLocationsHandler);{% else %}customLocationsHandler();{% endif %} })(jQuery, FC); </script> {% endif %}
Step 2: Add Custom Location Rules
Now the fun part, based on whatever criteria you want, add in the different country/state restrictions you require for your checkout. Add your custom code between the /* BEGIN CUSTOM LOCATION LOGIC */
and /* END CUSTOM LOCATION LOGIC */
lines at the top of the script block. There are five functions available to you.
FC.locations.removeCountries()
Removes the specified countries from the specified locations arrays
Parameters:
countries
(String or Array) - Either a string or an array of strings of the 2 character ISO country codeslocationArrayNames
(String or Array) - Optional - Either a string of either'billing'
,'shipping'
or'both'
, or an array of both like['billing', 'shipping']
. If not specified,'both'
is the automatic default.
Example:
FC.locations.removeCountries('US');
- Removes the United States from both the billing and the shipping country location fieldsFC.locations.removeCountries(['CA', 'GB'], 'shipping');
- Removes Canada and the United Kingdom from the shipping location fields
FC.locations.limitCountriesTo()
Restricts the specified locations arrays to just the countries specified
Parameters:
countries
(String or Array) - Either a string or an array of strings of the 2 character ISO country codeslocationArrayNames
(String or Array) - Optional - Either a string of either'billing'
,'shipping'
or'both'
, or an array of both like['billing', 'shipping']
. If not specified,'both'
is the automatic default.
Example:
FC.locations.limitCountriesTo('AU');
- Allows only Australia to be selected in the billing and shipping country location fieldsFC.locations.limitCountriesTo(['US', 'CA'], 'shipping');
- Allows only the United States and Canada to be selected for the shipping country
FC.locations.removeStates()
Removes the specified states from the specified locations arrays for the specified country
Parameters:
country
(String) - A string of the 2 character ISO country codesstates
(String or Array) - Either a string or an array of strings of the ISO state codeslocationArrayNames
(String or Array) - Optional - Either a string of either'billing'
,'shipping'
or'both'
, or an array of both like['billing', 'shipping']
. If not specified,'both'
is the automatic default.
Example:
FC.locations.removeStates('US', 'AK');
- Prevents Alaska from being selected as a state when the United States is selectedFC.locations.removeStates('US', ['AK', 'HI'], 'shipping');
- Prevents Alaska and Hawaii from being selected as a state for shipping when the United States is selected as the shipping country
FC.locations.limitStatesTo()
Restricts the states for the specified country to only those specified
Parameters:
country
(String) - A string of the 2 character ISO country codesstates
(String or Array) - Either a string or an array of strings of the ISO state codeslocationArrayNames
(String or Array) - Optional - Either a string of either'billing'
,'shipping'
or'both'
, or an array of both like['billing', 'shipping']
. If not specified,'both'
is the automatic default.
Example:
FC.locations.limitStatesTo('US', 'CA');
- Allows only California to be selected as a state when the United States is selectedFC.locations.limitStatesTo('AU', ['SA', 'VIC', 'QLD'], 'shipping');
- Allows only South Australia, Victoria and Queensland from being selected for shipping when Australia is selected as the shipping country.
FC.locations.reset()
Resets the location restrictions back to the store default, as set in the “configuration” in the Foxy administration. Best used through the javascript events on the cart/checkout to trigger the reset based on events, such as removing an item from the cart.
Parameters:
locationArrayNames
(String or Array) - Optional - Either a string of either'billing'
,'shipping'
or'both'
, or an array of both like['billing', 'shipping']
. If not specified,'both'
is the automatic default.
Example:
FC.locations.reset;
- Reset the location restrictions back to defaultFC.client.on('cart-item-remove.done', function() { FC.locations.reset(); });
- Reset location restrictions whenever an item is removed from the cart
Examples
Example 1
- Restricting the checkout to only allow shipping to the United States, but allow billing to be from any country
FC.locations.limitCountriesTo('US', 'shipping');
Example 2
- Only allow customers from the US and Canada, and not from Alaska or Hawaii.
FC.locations.limitCountriesTo(['US', 'CA']); FC.locations.removeStates('US', ['AK', 'HI']);
Example 3
- Remove all non-standard US States
FC.locations.removeStates('US', ['AF','AA','AC','AE','AM','AP','AS','PR','VI','GU','FM','MH','MP'], 'both');
Example 4
- Remove countries that are currently under sanction restrictions from the US Office of Foreign Assets Control (Note that this list may not be up to date)
FC.locations.removeCountries(['CU','IR','SD','KP']);
What about making it read-only?
As part of the new autocomplete functionality from version 1.0, any location object that only has one option will automatically become read-only with that location selected by default. If you want to set a field read only, utilise the limitCountriesTo()
or limitStatesTo()
functions with only a single location specified.
Changelog
- 2014/08/21 - v2.0 - Initial version
- 2019/11/09 - v2.1 - Adding
reset()
function - 2020/02/20 - v2.2 - Triggering
reset()
before the custom logic is run subsequent times on the same page