mirror of
https://github.com/10h30/woo-viet.git
synced 2026-06-05 15:09:49 +09:00
Add the wc-city-select plugin - version 1.0.3
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
jQuery( function($) {
|
||||
|
||||
// wc_city_select_params is required to continue, ensure the object exists
|
||||
// wc_country_select_params is used for select2 texts. This one is added by WC
|
||||
if ( typeof wc_country_select_params === 'undefined' || typeof wc_city_select_params === 'undefined' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getEnhancedSelectFormatString() {
|
||||
var formatString = {
|
||||
formatMatches: function( matches ) {
|
||||
if ( 1 === matches ) {
|
||||
return wc_country_select_params.i18n_matches_1;
|
||||
}
|
||||
|
||||
return wc_country_select_params.i18n_matches_n.replace( '%qty%', matches );
|
||||
},
|
||||
formatNoMatches: function() {
|
||||
return wc_country_select_params.i18n_no_matches;
|
||||
},
|
||||
formatAjaxError: function() {
|
||||
return wc_country_select_params.i18n_ajax_error;
|
||||
},
|
||||
formatInputTooShort: function( input, min ) {
|
||||
var number = min - input.length;
|
||||
|
||||
if ( 1 === number ) {
|
||||
return wc_country_select_params.i18n_input_too_short_1;
|
||||
}
|
||||
|
||||
return wc_country_select_params.i18n_input_too_short_n.replace( '%qty%', number );
|
||||
},
|
||||
formatInputTooLong: function( input, max ) {
|
||||
var number = input.length - max;
|
||||
|
||||
if ( 1 === number ) {
|
||||
return wc_country_select_params.i18n_input_too_long_1;
|
||||
}
|
||||
|
||||
return wc_country_select_params.i18n_input_too_long_n.replace( '%qty%', number );
|
||||
},
|
||||
formatSelectionTooBig: function( limit ) {
|
||||
if ( 1 === limit ) {
|
||||
return wc_country_select_params.i18n_selection_too_long_1;
|
||||
}
|
||||
|
||||
return wc_country_select_params.i18n_selection_too_long_n.replace( '%qty%', limit );
|
||||
},
|
||||
formatLoadMore: function() {
|
||||
return wc_country_select_params.i18n_load_more;
|
||||
},
|
||||
formatSearching: function() {
|
||||
return wc_country_select_params.i18n_searching;
|
||||
}
|
||||
};
|
||||
|
||||
return formatString;
|
||||
}
|
||||
|
||||
// Select2 Enhancement if it exists
|
||||
if ( $().select2 ) {
|
||||
var wc_city_select_select2 = function() {
|
||||
$( 'select.city_select:visible' ).each( function() {
|
||||
var select2_args = $.extend({
|
||||
placeholderOption: 'first',
|
||||
width: '100%'
|
||||
}, getEnhancedSelectFormatString() );
|
||||
|
||||
$( this ).select2( select2_args );
|
||||
});
|
||||
};
|
||||
|
||||
wc_city_select_select2();
|
||||
|
||||
$( document.body ).bind( 'city_to_select', function() {
|
||||
wc_city_select_select2();
|
||||
});
|
||||
}
|
||||
|
||||
/* City select boxes */
|
||||
var cities_json = wc_city_select_params.cities.replace( /"/g, '"' );
|
||||
var cities = $.parseJSON( cities_json );
|
||||
|
||||
$( 'body' ).on( 'country_to_state_changing', function(e, country, $container) {
|
||||
var $statebox = $container.find( '#billing_state, #shipping_state, #calc_shipping_state' );
|
||||
var state = $statebox.val();
|
||||
$( document.body ).trigger( 'state_changing', [country, state, $container ] );
|
||||
});
|
||||
|
||||
$( 'body' ).on( 'change', 'select.state_select, #calc_shipping_state', function() {
|
||||
var $container = $( this ).closest( 'div' );
|
||||
var country = $container.find( '#billing_country, #shipping_country, #calc_shipping_country' ).val();
|
||||
var state = $( this ).val();
|
||||
|
||||
$( document.body ).trigger( 'state_changing', [country, state, $container ] );
|
||||
});
|
||||
|
||||
$( 'body' ).on( 'state_changing', function(e, country, state, $container) {
|
||||
var $citybox = $container.find( '#billing_city, #shipping_city, #calc_shipping_city' );
|
||||
|
||||
if ( cities[ country ] ) {
|
||||
/* if the country has no states */
|
||||
if( cities[country] instanceof Array) {
|
||||
cityToSelect( $citybox, cities[ country ] );
|
||||
} else if ( state ) {
|
||||
if ( cities[ country ][ state ] ) {
|
||||
cityToSelect( $citybox, cities[ country ][ state ] );
|
||||
} else {
|
||||
cityToInput( $citybox );
|
||||
}
|
||||
} else {
|
||||
disableCity( $citybox );
|
||||
}
|
||||
} else {
|
||||
cityToInput( $citybox );
|
||||
}
|
||||
});
|
||||
|
||||
/* Ajax replaces .cart_totals (child of .cart-collaterals) on shipping calculator */
|
||||
if ( $( '.cart-collaterals' ).length && $( '#calc_shipping_state' ).length ) {
|
||||
var calc_observer = new MutationObserver( function() {
|
||||
$( '#calc_shipping_state' ).change();
|
||||
});
|
||||
calc_observer.observe( document.querySelector( '.cart-collaterals' ), { childList: true });
|
||||
}
|
||||
|
||||
function cityToInput( $citybox ) {
|
||||
if ( $citybox.is('input') ) {
|
||||
$citybox.prop( 'disabled', false );
|
||||
return;
|
||||
}
|
||||
|
||||
var input_name = $citybox.attr( 'name' );
|
||||
var input_id = $citybox.attr( 'id' );
|
||||
var placeholder = $citybox.attr( 'placeholder' );
|
||||
|
||||
$citybox.parent().find( '.select2-container' ).remove();
|
||||
|
||||
$citybox.replaceWith( '<input type="text" class="input-text" name="' + input_name + '" id="' + input_id + '" placeholder="' + placeholder + '" />' );
|
||||
}
|
||||
|
||||
function disableCity( $citybox ) {
|
||||
$citybox.val( '' ).change();
|
||||
$citybox.prop( 'disabled', true );
|
||||
}
|
||||
|
||||
function cityToSelect( $citybox, current_cities ) {
|
||||
var value = $citybox.val();
|
||||
|
||||
if ( $citybox.is('input') ) {
|
||||
var input_name = $citybox.attr( 'name' );
|
||||
var input_id = $citybox.attr( 'id' );
|
||||
var placeholder = $citybox.attr( 'placeholder' );
|
||||
|
||||
$citybox.replaceWith( '<select name="' + input_name + '" id="' + input_id + '" class="city_select" placeholder="' + placeholder + '"></select>' );
|
||||
//we have to assign the new object, because of replaceWith
|
||||
$citybox = $('#'+input_id);
|
||||
} else {
|
||||
$citybox.prop( 'disabled', false );
|
||||
}
|
||||
|
||||
var options = '';
|
||||
for( var index in current_cities ) {
|
||||
if ( current_cities.hasOwnProperty( index ) ) {
|
||||
var cityName = current_cities[ index ];
|
||||
options = options + '<option value="' + cityName + '">' + cityName + '</option>';
|
||||
}
|
||||
}
|
||||
|
||||
$citybox.html( '<option value="">' + wc_city_select_params.i18n_select_city_text + '</option>' + options );
|
||||
|
||||
if ( $('option[value="'+value+'"]', $citybox).length ) {
|
||||
$citybox.val( value ).change();
|
||||
} else {
|
||||
$citybox.val( '' ).change();
|
||||
}
|
||||
|
||||
$( document.body ).trigger( 'city_to_select' );
|
||||
}
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,79 @@
|
||||
=== WC City Select ===
|
||||
Contributors: mantish
|
||||
Donate link: mailto:paypal@8manos.com
|
||||
Tags: woocommerce, cities, city, city select, cities select, city dropdown, cities dropdown, woocommerce city, woocommerce cities
|
||||
Requires at least: 4.0
|
||||
Tested up to: 4.7.3
|
||||
Stable tag: 1.0.3
|
||||
WC requires at least: 2.2
|
||||
WC tested up to: 2.7.0
|
||||
License: GPLv2 or later
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
City Select for WooCommerce. Show a dropdown select as the cities input.
|
||||
|
||||
== Description ==
|
||||
|
||||
WooCommerce uses a text input for the customers to enter the city or town. With this plugin you can provide a list of cities to be shown as a select dropdown.
|
||||
|
||||
This will be shown in checkout pages, edit addresses pages and shipping calculator if it's configured that way.
|
||||
|
||||
A list of cities has to be loaded in the functions.php file (the plugin already includes cities from Colombia and Iran). Please check the Installation section for more info.
|
||||
|
||||
### Github
|
||||
|
||||
Contribute at https://github.com/8manos/wc-city-select
|
||||
|
||||
== Installation ==
|
||||
|
||||
1. Upload to the `/wp-content/plugins/` directory
|
||||
1. Activate the plugin through the 'Plugins' menu in WordPress
|
||||
1. Use `wc_city_select_cities` filter to load your cities. This is done similarly to [adding states/provinces](https://docs.woothemes.com/document/addmodify-states/). It should be added on your functions.php or a custom plugin.
|
||||
|
||||
`
|
||||
add_filter( 'wc_city_select_cities', 'my_cities' );
|
||||
/**
|
||||
* Replace XX with the country code. Instead of YYY, ZZZ use actual state codes.
|
||||
*/
|
||||
function my_cities( $cities ) {
|
||||
$cities['XX'] = array(
|
||||
'YYY' => array(
|
||||
'City ',
|
||||
'Another City'
|
||||
),
|
||||
'ZZZ' => array(
|
||||
'City 3',
|
||||
'City 4'
|
||||
)
|
||||
);
|
||||
return $cities;
|
||||
}
|
||||
`
|
||||
|
||||
It's also possible to use a list of cities without grouping them by state:
|
||||
|
||||
`
|
||||
add_filter( 'wc_city_select_cities', 'my_cities' );
|
||||
function my_cities( $cities ) {
|
||||
$cities['XX'] = array(
|
||||
'City ',
|
||||
'Another City'
|
||||
);
|
||||
return $cities;
|
||||
}
|
||||
`
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 1.0.3 =
|
||||
* fix some issues when loading cities initially, that were causing warnings.
|
||||
|
||||
= 1.0.2 =
|
||||
* fix some issues with shipping calculator and other edge cases.
|
||||
* Now works with countries that have no states, only cities.
|
||||
|
||||
= 1.0.1 =
|
||||
* select2 enhancement when available. Adds a JS version of the select dropdown.
|
||||
|
||||
= 1.0 =
|
||||
* First release.
|
||||
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: WC City Select
|
||||
* Plugin URI: https://wordpress.org/plugins/wc-city-select/
|
||||
* Description: City Select for WooCommerce. Show a dropdown select as the cities input.
|
||||
* Version: 1.0.3
|
||||
* Author: 8manos
|
||||
* Author URI: http://8manos.com
|
||||
* License: GPLv2 or later
|
||||
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
||||
|
||||
// Check if WooCommerce is active
|
||||
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
|
||||
|
||||
class WC_City_Select {
|
||||
|
||||
// plugin version
|
||||
const VERSION = '1.0.1';
|
||||
|
||||
private $plugin_path;
|
||||
private $plugin_url;
|
||||
|
||||
private $cities;
|
||||
|
||||
public function __construct() {
|
||||
add_filter( 'woocommerce_billing_fields', array( $this, 'billing_fields' ), 10, 2 );
|
||||
add_filter( 'woocommerce_shipping_fields', array( $this, 'shipping_fields' ), 10, 2 );
|
||||
add_filter( 'woocommerce_form_field_city', array( $this, 'form_field_city' ), 10, 4 );
|
||||
|
||||
//js scripts
|
||||
add_action( 'wp_enqueue_scripts', array( $this, 'load_scripts' ) );
|
||||
}
|
||||
|
||||
public function billing_fields( $fields, $country ) {
|
||||
$fields['billing_city']['type'] = 'city';
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function shipping_fields( $fields, $country ) {
|
||||
$fields['shipping_city']['type'] = 'city';
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function get_cities( $cc = null ) {
|
||||
if ( empty( $this->cities ) ) {
|
||||
$this->load_country_cities();
|
||||
}
|
||||
|
||||
if ( ! is_null( $cc ) ) {
|
||||
return isset( $this->cities[ $cc ] ) ? $this->cities[ $cc ] : false;
|
||||
} else {
|
||||
return $this->cities;
|
||||
}
|
||||
}
|
||||
|
||||
public function load_country_cities() {
|
||||
global $cities;
|
||||
|
||||
// Load only the city files the shop owner wants/needs.
|
||||
$allowed = array_merge( WC()->countries->get_allowed_countries(), WC()->countries->get_shipping_countries() );
|
||||
|
||||
if ( $allowed ) {
|
||||
foreach ( $allowed as $code => $country ) {
|
||||
if ( ! isset( $cities[ $code ] ) && file_exists( $this->get_plugin_path() . '/cities/' . $code . '.php' ) ) {
|
||||
include( $this->get_plugin_path() . '/cities/' . $code . '.php' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->cities = apply_filters( 'wc_city_select_cities', $cities );
|
||||
}
|
||||
|
||||
public function form_field_city( $field, $key, $args, $value ) {
|
||||
|
||||
// Do we need a clear div?
|
||||
if ( ( ! empty( $args['clear'] ) ) ) {
|
||||
$after = '<div class="clear"></div>';
|
||||
} else {
|
||||
$after = '';
|
||||
}
|
||||
|
||||
// Required markup
|
||||
if ( $args['required'] ) {
|
||||
$args['class'][] = 'validate-required';
|
||||
$required = ' <abbr class="required" title="' . esc_attr__( 'required', 'woocommerce' ) . '">*</abbr>';
|
||||
} else {
|
||||
$required = '';
|
||||
}
|
||||
|
||||
// Custom attribute handling
|
||||
$custom_attributes = array();
|
||||
|
||||
if ( ! empty( $args['custom_attributes'] ) && is_array( $args['custom_attributes'] ) ) {
|
||||
foreach ( $args['custom_attributes'] as $attribute => $attribute_value ) {
|
||||
$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
|
||||
}
|
||||
}
|
||||
|
||||
// Validate classes
|
||||
if ( ! empty( $args['validate'] ) ) {
|
||||
foreach( $args['validate'] as $validate ) {
|
||||
$args['class'][] = 'validate-' . $validate;
|
||||
}
|
||||
}
|
||||
|
||||
// field p and label
|
||||
$field = '<p class="form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $args['id'] ) . '_field">';
|
||||
if ( $args['label'] ) {
|
||||
$field .= '<label for="' . esc_attr( $args['id'] ) . '" class="' . esc_attr( implode( ' ', $args['label_class'] ) ) .'">' . $args['label']. $required . '</label>';
|
||||
}
|
||||
|
||||
// Get Country
|
||||
$country_key = $key == 'billing_city' ? 'billing_country' : 'shipping_country';
|
||||
$current_cc = WC()->checkout->get_value( $country_key );
|
||||
|
||||
$state_key = $key == 'billing_city' ? 'billing_state' : 'shipping_state';
|
||||
$current_sc = WC()->checkout->get_value( $state_key );
|
||||
|
||||
// Get country cities
|
||||
$cities = $this->get_cities( $current_cc );
|
||||
|
||||
if ( is_array( $cities ) ) {
|
||||
|
||||
$field .= '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" class="city_select ' . esc_attr( implode( ' ', $args['input_class'] ) ) .'" ' . implode( ' ', $custom_attributes ) . ' placeholder="' . esc_attr( $args['placeholder'] ) . '">
|
||||
<option value="">'. __( 'Select an option…', 'woocommerce' ) .'</option>';
|
||||
|
||||
if ( $current_sc && $cities[ $current_sc ] ) {
|
||||
$dropdown_cities = $cities[ $current_sc ];
|
||||
} else if ( is_array( reset($cities) ) ) {
|
||||
$dropdown_cities = array_reduce( $cities, 'array_merge', array() );
|
||||
sort( $dropdown_cities );
|
||||
} else {
|
||||
$dropdown_cities = $cities;
|
||||
}
|
||||
|
||||
foreach ( $dropdown_cities as $city_name ) {
|
||||
$field .= '<option value="' . esc_attr( $city_name ) . '" '.selected( $value, $city_name, false ) . '>' . $city_name .'</option>';
|
||||
}
|
||||
|
||||
$field .= '</select>';
|
||||
|
||||
} else {
|
||||
|
||||
$field .= '<input type="text" class="input-text ' . esc_attr( implode( ' ', $args['input_class'] ) ) .'" value="' . esc_attr( $value ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" ' . implode( ' ', $custom_attributes ) . ' />';
|
||||
}
|
||||
|
||||
// field description and close wrapper
|
||||
if ( $args['description'] ) {
|
||||
$field .= '<span class="description">' . esc_attr( $args['description'] ) . '</span>';
|
||||
}
|
||||
|
||||
$field .= '</p>' . $after;
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
||||
public function load_scripts() {
|
||||
if ( is_cart() || is_checkout() || is_wc_endpoint_url( 'edit-address' ) ) {
|
||||
|
||||
$city_select_path = $this->get_plugin_url() . 'assets/js/city-select.js';
|
||||
wp_enqueue_script( 'wc-city-select', $city_select_path, array( 'jquery', 'woocommerce' ), self::VERSION, true );
|
||||
|
||||
$cities = json_encode( $this->get_cities() );
|
||||
wp_localize_script( 'wc-city-select', 'wc_city_select_params', array(
|
||||
'cities' => $cities,
|
||||
'i18n_select_city_text' => esc_attr__( 'Select an option…', 'woocommerce' )
|
||||
) );
|
||||
}
|
||||
}
|
||||
|
||||
public function get_plugin_path() {
|
||||
|
||||
if ( $this->plugin_path ) {
|
||||
return $this->plugin_path;
|
||||
}
|
||||
|
||||
return $this->plugin_path = plugin_dir_path( __FILE__ );
|
||||
}
|
||||
|
||||
public function get_plugin_url() {
|
||||
|
||||
if ( $this->plugin_url ) {
|
||||
return $this->plugin_url;
|
||||
}
|
||||
|
||||
return $this->plugin_url = plugin_dir_url( __FILE__ );
|
||||
}
|
||||
}
|
||||
|
||||
$GLOBALS['wc_city_select'] = new WC_City_Select();
|
||||
}
|
||||
Reference in New Issue
Block a user