Skip to content

Instantly share code, notes, and snippets.

@igorbenic
Created May 26, 2023 15:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save igorbenic/277cf5095e77d00e30101d5768b9884e to your computer and use it in GitHub Desktop.
Save igorbenic/277cf5095e77d00e30101d5768b9884e to your computer and use it in GitHub Desktop.
How to add a City Dropdown to WooCommerce Checkout
jQuery( function( $ ) {
var cities = wc_city_dropdown.cities;
wrapper_selectors = '.woocommerce-billing-fields,' +
'.woocommerce-shipping-fields,' +
'.woocommerce-address-fields';
$( document.body ).on( 'change refresh', 'select.country_to_state, input.country_to_state', function() {
var $wrapper = $( this ).closest( wrapper_selectors );
if ( ! $wrapper.length ) {
$wrapper = $( this ).closest('.form-row').parent();
}
var country = $( this ).val(),
$citybox = $wrapper.find( '#billing_city, #shipping_city' ),
$parent = $citybox.closest( '.form-row' ),
input_name = $citybox.attr( 'name' ),
input_id = $citybox.attr('id'),
input_classes = $citybox.attr('data-input-classes'),
value = $citybox.val(),
placeholder = $citybox.attr( 'placeholder' ) || $citybox.attr( 'data-placeholder' ) || '',
$newcity;
// next code here
});
})
jQuery( function( $ ) {
var cities = wc_city_dropdown.cities;
wrapper_selectors = '.woocommerce-billing-fields,' +
'.woocommerce-shipping-fields,' +
'.woocommerce-address-fields';
$( document.body ).on( 'change refresh', 'select.country_to_state, input.country_to_state', function() {
// ... previous code
// If we have cities for a country, let's create a dropdown
// In case we have a country defined here, but no cities at all, we'll add a hidden field.
if ( cities[ country ] ) {
if ( $.isEmptyObject( cities[ country ] ) ) {
$newcity = $( '<input type="hidden" />' )
.prop( 'id', input_id )
.prop( 'name', input_name )
.prop( 'placeholder', placeholder )
.attr( 'data-input-classes', input_classes )
.addClass( 'hidden ' + input_classes );
$parent.hide().find( '.select2-container' ).remove();
$citybox.replaceWith( $newcity );
$( document.body ).trigger( 'country_to_city_changed', [ country, $wrapper ] );
} else {
var city = cities[country],
$defaultOption = $('<option value=""></option>').text('Select a City');
if (!placeholder) {
placeholder = 'Select a City';
}
$parent.show();
if ($citybox.is('input')) {
$newcity = $('<select></select>')
.prop('id', input_id)
.prop('name', input_name)
.data('placeholder', placeholder)
.attr('data-input-classes', input_classes)
.addClass('state_select ' + input_classes);
$citybox.replaceWith($newcity);
$citybox = $wrapper.find('#billing_city, #shipping_city');
}
$citybox.empty().append($defaultOption);
$.each(city, function (index) {
var $option = $('<option></option>')
.prop('value', index)
.text(city[index]);
$citybox.append($option);
});
$citybox.val(value).trigger('change');
$( document.body ).trigger( 'country_to_city_changed', [country, $wrapper ] );
}
} else {
// No cities found and no country found? Create a regular text input field.
if ( $citybox.is( 'select, input[type="hidden"]' ) ) {
$newcity = $( '<input type="text" />' )
.prop( 'id', input_id )
.prop( 'name', input_name )
.prop('placeholder', placeholder)
.attr('data-input-classes', input_classes )
.addClass( 'input-text ' + input_classes );
$parent.show().find( '.select2-container' ).remove();
$citybox.replaceWith( $newcity );
$( document.body ).trigger( 'country_to_city_changed', [country, $wrapper ] );
}
}
$( document.body ).trigger( 'country_to_city_changing', [country, $wrapper ] );
});
})
jQuery( function( $ ) {
var cities = wc_city_dropdown.cities;
wrapper_selectors = '.woocommerce-billing-fields,' +
'.woocommerce-shipping-fields,' +
'.woocommerce-address-fields';
$( document.body ).on( 'change refresh', 'select.country_to_state, input.country_to_state', function() {
var $wrapper = $( this ).closest( wrapper_selectors );
if ( ! $wrapper.length ) {
$wrapper = $( this ).closest('.form-row').parent();
}
var country = $( this ).val(),
$citybox = $wrapper.find( '#billing_city, #shipping_city' ),
$parent = $citybox.closest( '.form-row' ),
input_name = $citybox.attr( 'name' ),
input_id = $citybox.attr('id'),
input_classes = $citybox.attr('data-input-classes'),
value = $citybox.val(),
placeholder = $citybox.attr( 'placeholder' ) || $citybox.attr( 'data-placeholder' ) || '',
$newcity;
if ( cities[ country ] ) {
if ( $.isEmptyObject( cities[ country ] ) ) {
$newcity = $( '<input type="hidden" />' )
.prop( 'id', input_id )
.prop( 'name', input_name )
.prop( 'placeholder', placeholder )
.attr( 'data-input-classes', input_classes )
.addClass( 'hidden ' + input_classes );
$parent.hide().find( '.select2-container' ).remove();
$citybox.replaceWith( $newcity );
$( document.body ).trigger( 'country_to_city_changed', [ country, $wrapper ] );
} else {
var city = cities[country],
$defaultOption = $('<option value=""></option>').text('Select a City');
if (!placeholder) {
placeholder = 'Select a City';
}
$parent.show();
if ($citybox.is('input')) {
$newcity = $('<select></select>')
.prop('id', input_id)
.prop('name', input_name)
.data('placeholder', placeholder)
.attr('data-input-classes', input_classes)
.addClass('state_select ' + input_classes);
$citybox.replaceWith($newcity);
$citybox = $wrapper.find('#billing_city, #shipping_city');
}
$citybox.empty().append($defaultOption);
$.each(city, function (index) {
var $option = $('<option></option>')
.prop('value', index)
.text(city[index]);
$citybox.append($option);
});
$citybox.val(value).trigger('change');
$( document.body ).trigger( 'country_to_city_changed', [country, $wrapper ] );
}
} else {
if ( $citybox.is( 'select, input[type="hidden"]' ) ) {
$newcity = $( '<input type="text" />' )
.prop( 'id', input_id )
.prop( 'name', input_name )
.prop('placeholder', placeholder)
.attr('data-input-classes', input_classes )
.addClass( 'input-text ' + input_classes );
$parent.show().find( '.select2-container' ).remove();
$citybox.replaceWith( $newcity );
$( document.body ).trigger( 'country_to_city_changed', [country, $wrapper ] );
}
}
$( document.body ).trigger( 'country_to_city_changing', [country, $wrapper ] );
});
})
function myplugin_enqueue() {
if ( ! function_exists( 'is_checkout' ) ) {
return;
}
if ( ! is_checkout() ) {
return;
}
wp_enqueue_script(
'wc-city-dropdown',
trailingslashit( plugin_dir_url( __FILE__ ) ) . 'assets/checkout.js',
[ 'jquery' ],
filemtime( trailingslashit( plugin_dir_path( __FILE__ ) ) . 'assets/checkout.js' ),
true
);
wp_localize_script( 'wc-city-dropdown', 'wc_city_dropdown', [
'cities' => myplugin_get_cities()
]);
}
function myplugin_get_cities() {
$cities = [
'US' => [
'New York' => 'New York',
'Texas' => 'Texas',
],
'IT' => [
'Rome' => 'Rome',
'Venezia' => 'Venezia',
]
];
return $cities;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment