From 74f3972e26c9a179401a3467db2d897162a09398 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Mon, 12 Dec 2016 15:23:28 +0000 Subject: [PATCH] Add sort parameter to checkout fields to aid with sorting per locale. --- assets/js/frontend/address-i18n.js | 52 ++++--- assets/js/frontend/address-i18n.min.js | 2 +- includes/class-wc-countries.php | 162 ++++++++++++++-------- includes/wc-template-functions.php | 8 +- readme.txt | 1 + templates/myaccount/form-edit-address.php | 22 +-- 6 files changed, 162 insertions(+), 85 deletions(-) diff --git a/assets/js/frontend/address-i18n.js b/assets/js/frontend/address-i18n.js index 20062980087..331bba7e67b 100644 --- a/assets/js/frontend/address-i18n.js +++ b/assets/js/frontend/address-i18n.js @@ -3,7 +3,7 @@ jQuery( function( $ ) { // wc_address_i18n_params is required to continue, ensure the object exists if ( typeof wc_address_i18n_params === 'undefined' ) { - return false; + return false; } var locale_json = wc_address_i18n_params.locale.replace( /"/g, '"' ), @@ -42,20 +42,6 @@ jQuery( function( $ ) { $statefield.attr( 'data-o_class', $statefield.attr( 'class' ) ); } - // Re-order postcode/city - if ( thislocale.postcode_before_city ) { - $postcodefield.add( $cityfield ).add( $statefield ).removeClass( 'form-row-first form-row-last' ).addClass( 'form-row-first' ); - $cityfield.removeClass( 'form-row-wide form-row-first' ).addClass( 'form-row-last' ); - $postcodefield.insertBefore( $cityfield ); - } else { - // Default - $postcodefield.attr( 'class', $postcodefield.attr( 'data-o_class' ) ); - $cityfield.attr( 'class', $cityfield.attr( 'data-o_class' ) ); - $statefield.attr( 'class', $statefield.attr( 'data-o_class' ) ); - $postcodefield.insertAfter( $statefield ); - } - - // Handle locale fields var locale_fields = $.parseJSON( wc_address_i18n_params.locale_fields ); $.each( locale_fields, function( key, value ) { @@ -88,6 +74,12 @@ jQuery( function( $ ) { } } + if ( thislocale[ key ].sort ) { + field.data( 'sort', thislocale[ key ].sort ); + } else if ( locale['default'][ key ].sort ) { + field.data( 'sort', locale['default'][ key ].sort ); + } + } else if ( locale['default'][ key ] ) { if ( 'state' !== key ) { @@ -113,9 +105,37 @@ jQuery( function( $ ) { field_is_required( field, true ); } } + + if ( locale['default'][ key ].sort ) { + field.data( 'sort', locale['default'][ key ].sort ); + } } }); - }); + var fieldsets = $('.woocommerce-billing-fields, .woocommerce-shipping-fields, .woocommerce-address-fields'); + + fieldsets.each( function( index, fieldset ) { + var rows = $( fieldset ).find('.form-row'); + + rows.sort(function( a, b ){ + var asort = $(a).data('sort'), + bsort = $(b).data('sort'); + + if ( ! asort || ! bsort ) { + return 0; + } + + if ( asort > bsort ) { + return 1; + } + if ( asort < bsort ) { + return -1; + } + return 0; + }); + + rows.detach().prependTo( fieldset ); + } ); + }); }); diff --git a/assets/js/frontend/address-i18n.min.js b/assets/js/frontend/address-i18n.min.js index f49f826a0fb..56a50911407 100644 --- a/assets/js/frontend/address-i18n.min.js +++ b/assets/js/frontend/address-i18n.min.js @@ -1 +1 @@ -jQuery(function(a){function b(a,b){b?(a.find("label").append(' *'),a.addClass("validate-required")):(a.find("label abbr").remove(),a.removeClass("validate-required"))}if("undefined"==typeof wc_address_i18n_params)return!1;var c=wc_address_i18n_params.locale.replace(/"/g,'"'),d=a.parseJSON(c);a(document.body).bind("country_to_state_changing",function(c,e,f){var g,h=f;g="undefined"!=typeof d[e]?d[e]:d["default"];var i=h.find("#billing_postcode_field, #shipping_postcode_field"),j=h.find("#billing_city_field, #shipping_city_field"),k=h.find("#billing_state_field, #shipping_state_field");i.attr("data-o_class")||(i.attr("data-o_class",i.attr("class")),j.attr("data-o_class",j.attr("class")),k.attr("data-o_class",k.attr("class"))),g.postcode_before_city?(i.add(j).add(k).removeClass("form-row-first form-row-last").addClass("form-row-first"),j.removeClass("form-row-wide form-row-first").addClass("form-row-last"),i.insertBefore(j)):(i.attr("class",i.attr("data-o_class")),j.attr("class",j.attr("data-o_class")),k.attr("class",k.attr("data-o_class")),i.insertAfter(k));var l=a.parseJSON(wc_address_i18n_params.locale_fields);a.each(l,function(a,c){var e=h.find(c);g[a]?(g[a].label&&e.find("label").html(g[a].label),g[a].placeholder&&e.find("input").attr("placeholder",g[a].placeholder),b(e,!1),"undefined"==typeof g[a].required&&d["default"][a].required===!0?b(e,!0):g[a].required===!0&&b(e,!0),"state"!==a&&(g[a].hidden===!0?e.hide().find("input").val(""):e.show())):d["default"][a]&&("state"!==a&&("undefined"==typeof d["default"][a].hidden||d["default"][a].hidden===!1?e.show():d["default"][a].hidden===!0&&e.hide().find("input").val("")),"postcode"!==a&&"city"!==a&&"state"!==a||(d["default"][a].label&&e.find("label").html(d["default"][a].label),d["default"][a].placeholder&&e.find("input").attr("placeholder",d["default"][a].placeholder)),d["default"][a].required===!0&&0===e.find("label abbr").length&&b(e,!0))})})}); \ No newline at end of file +jQuery(function(a){function b(a,b){b?(a.find("label").append(' *'),a.addClass("validate-required")):(a.find("label abbr").remove(),a.removeClass("validate-required"))}if("undefined"==typeof wc_address_i18n_params)return!1;var c=wc_address_i18n_params.locale.replace(/"/g,'"'),d=a.parseJSON(c);a(document.body).bind("country_to_state_changing",function(c,e,f){var g,h=f;g="undefined"!=typeof d[e]?d[e]:d["default"];var i=h.find("#billing_postcode_field, #shipping_postcode_field"),j=h.find("#billing_city_field, #shipping_city_field"),k=h.find("#billing_state_field, #shipping_state_field");i.attr("data-o_class")||(i.attr("data-o_class",i.attr("class")),j.attr("data-o_class",j.attr("class")),k.attr("data-o_class",k.attr("class")));var l=a.parseJSON(wc_address_i18n_params.locale_fields);a.each(l,function(a,c){var e=h.find(c);g[a]?(g[a].label&&e.find("label").html(g[a].label),g[a].placeholder&&e.find("input").attr("placeholder",g[a].placeholder),b(e,!1),"undefined"==typeof g[a].required&&d["default"][a].required===!0?b(e,!0):g[a].required===!0&&b(e,!0),"state"!==a&&(g[a].hidden===!0?e.hide().find("input").val(""):e.show()),g[a].sort?e.data("sort",g[a].sort):d["default"][a].sort&&e.data("sort",d["default"][a].sort)):d["default"][a]&&("state"!==a&&("undefined"==typeof d["default"][a].hidden||d["default"][a].hidden===!1?e.show():d["default"][a].hidden===!0&&e.hide().find("input").val("")),"postcode"!==a&&"city"!==a&&"state"!==a||(d["default"][a].label&&e.find("label").html(d["default"][a].label),d["default"][a].placeholder&&e.find("input").attr("placeholder",d["default"][a].placeholder)),d["default"][a].required===!0&&0===e.find("label abbr").length&&b(e,!0),d["default"][a].sort&&e.data("sort",d["default"][a].sort))});var m=a(".woocommerce-billing-fields, .woocommerce-shipping-fields, .woocommerce-address-fields");m.each(function(b,c){var d=a(c).find(".form-row");d.sort(function(b,c){var d=a(b).data("sort"),e=a(c).data("sort");return d&&e?d>e?1:daddress_formats ) ) { - - // Common formats - $postcode_before_city = "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}"; - - // Define address formats $this->address_formats = apply_filters( 'woocommerce_localisation_address_formats', array( 'default' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}\n{state}\n{postcode}\n{country}", 'AU' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}", - 'AT' => $postcode_before_city, - 'BE' => $postcode_before_city, + 'AT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'BE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", 'CA' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}", - 'CH' => $postcode_before_city, + 'CH' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", 'CL' => "{company}\n{name}\n{address_1}\n{address_2}\n{state}\n{postcode} {city}\n{country}", 'CN' => "{country} {postcode}\n{state}, {city}, {address_2}, {address_1}\n{company}\n{name}", - 'CZ' => $postcode_before_city, - 'DE' => $postcode_before_city, - 'EE' => $postcode_before_city, - 'FI' => $postcode_before_city, - 'DK' => $postcode_before_city, + 'CZ' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'DE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'EE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'FI' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'DK' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", 'FR' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city_upper}\n{country}", 'HK' => "{company}\n{first_name} {last_name_upper}\n{address_1}\n{address_2}\n{city_upper}\n{state_upper}\n{country}", 'HU' => "{name}\n{company}\n{city}\n{address_1}\n{address_2}\n{postcode}\n{country}", 'IN' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} - {postcode}\n{state}, {country}", - 'IS' => $postcode_before_city, + 'IS' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", 'IT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode}\n{city}\n{state_upper}\n{country}", 'JP' => "{postcode}\n{state}{city}{address_1}\n{address_2}\n{company}\n{last_name} {first_name}\n{country}", 'TW' => "{company}\n{last_name} {first_name}\n{address_1}\n{address_2}\n{state}, {city} {postcode}\n{country}", - 'LI' => $postcode_before_city, - 'NL' => $postcode_before_city, + 'LI' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'NL' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", 'NZ' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {postcode}\n{country}", - 'NO' => $postcode_before_city, - 'PL' => $postcode_before_city, - 'PT' => $postcode_before_city, - 'SK' => $postcode_before_city, - 'SI' => $postcode_before_city, + 'NO' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'PL' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'PT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'SK' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'SI' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", 'ES' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city}\n{state}\n{country}", - 'SE' => $postcode_before_city, + 'SE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", 'TR' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city} {state}\n{country}", 'US' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}, {state_code} {postcode}\n{country}", 'VN' => "{name}\n{company}\n{address_1}\n{city}\n{country}", - )); + ) ); } - return $this->address_formats; } @@ -554,6 +551,7 @@ class WC_Countries { 'class' => array( 'form-row-first' ), 'autocomplete' => 'given-name', 'autofocus' => true, + 'sort' => 10, ), 'last_name' => array( 'label' => __( 'Last name', 'woocommerce' ), @@ -561,11 +559,13 @@ class WC_Countries { 'class' => array( 'form-row-last' ), 'clear' => true, 'autocomplete' => 'family-name', + 'sort' => 20, ), 'company' => array( 'label' => __( 'Company name', 'woocommerce' ), 'class' => array( 'form-row-wide' ), 'autocomplete' => 'organization', + 'sort' => 30, ), 'country' => array( 'type' => 'country', @@ -573,6 +573,7 @@ class WC_Countries { 'required' => true, 'class' => array( 'form-row-wide', 'address-field', 'update_totals_on_change' ), 'autocomplete' => 'country', + 'sort' => 40, ), 'address_1' => array( 'label' => __( 'Address', 'woocommerce' ), @@ -580,34 +581,39 @@ class WC_Countries { 'required' => true, 'class' => array( 'form-row-wide', 'address-field' ), 'autocomplete' => 'address-line1', + 'sort' => 50, ), 'address_2' => array( 'placeholder' => esc_attr__( 'Apartment, suite, unit etc. (optional)', 'woocommerce' ), 'class' => array( 'form-row-wide', 'address-field' ), 'required' => false, 'autocomplete' => 'address-line2', + 'sort' => 60, ), 'city' => array( 'label' => __( 'Town / City', 'woocommerce' ), 'required' => true, 'class' => array( 'form-row-wide', 'address-field' ), 'autocomplete' => 'address-level2', + 'sort' => 70, ), 'state' => array( 'type' => 'state', 'label' => __( 'State / County', 'woocommerce' ), 'required' => true, - 'class' => array( 'form-row-first', 'address-field' ), + 'class' => array( 'form-row-wide', 'address-field' ), 'validate' => array( 'state' ), 'autocomplete' => 'address-level1', + 'sort' => 80, ), 'postcode' => array( 'label' => __( 'Postcode / ZIP', 'woocommerce' ), 'required' => true, - 'class' => array( 'form-row-last', 'address-field' ), + 'class' => array( 'form-row-wide', 'address-field' ), 'clear' => true, 'validate' => array( 'postcode' ), 'autocomplete' => 'postal-code', + 'sort' => 90, ), ); @@ -631,12 +637,13 @@ class WC_Countries { /** * Get country locale settings. + * + * These locales override the default country selections after a country is chosen. + * * @return array */ public function get_country_locale() { if ( empty( $this->locale ) ) { - - // Locale information used by the checkout $this->locale = apply_filters( 'woocommerce_get_country_locale', array( 'AE' => array( 'postcode' => array( @@ -650,7 +657,9 @@ class WC_Countries { ), ), 'AT' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, ), @@ -667,7 +676,9 @@ class WC_Countries { ), ), 'AX' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, ), @@ -681,7 +692,9 @@ class WC_Countries { ), ), 'BE' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, 'label' => __( 'Province', 'woocommerce' ), @@ -710,7 +723,9 @@ class WC_Countries { ), ), 'CH' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'label' => __( 'Canton', 'woocommerce' ), 'required' => false, @@ -743,31 +758,41 @@ class WC_Countries { ), ), 'DE' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, ), ), 'DK' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, ), ), 'EE' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, ), ), 'FI' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, ), ), 'FR' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, ), @@ -803,19 +828,25 @@ class WC_Countries { ), ), 'IS' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, ), ), 'IL' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, ), ), 'IT' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => true, 'label' => __( 'Province', 'woocommerce' ), @@ -824,6 +855,10 @@ class WC_Countries { 'JP' => array( 'state' => array( 'label' => __( 'Prefecture', 'woocommerce' ), + 'sort' => 66, + ), + 'postcode' => array( + 'sort' => 65, ), ), 'KR' => array( @@ -832,7 +867,9 @@ class WC_Countries { ), ), 'NL' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, 'label' => __( 'Province', 'woocommerce' ), @@ -848,7 +885,9 @@ class WC_Countries { ), ), 'NO' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, ), @@ -862,7 +901,9 @@ class WC_Countries { ), ), 'PL' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, ), @@ -883,25 +924,33 @@ class WC_Countries { ), ), 'SK' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, ), ), 'SI' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, ), ), 'ES' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'label' => __( 'Province', 'woocommerce' ), ), ), 'LI' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'label' => __( 'Municipality', 'woocommerce' ), 'required' => false, @@ -913,13 +962,17 @@ class WC_Countries { ), ), 'SE' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'required' => false, ), ), 'TR' => array( - 'postcode_before_city' => true, + 'postcode' => array( + 'sort' => 65, + ), 'state' => array( 'label' => __( 'Province', 'woocommerce' ), ), @@ -942,11 +995,11 @@ class WC_Countries { ), ), 'VN' => array( - 'postcode_before_city' => true, 'state' => array( 'required' => false, ), 'postcode' => array( + 'sort' => 65, 'required' => false, 'hidden' => false, ), @@ -976,8 +1029,7 @@ class WC_Countries { $this->locale = array_intersect_key( $this->locale, array_merge( $this->get_allowed_countries(), $this->get_shipping_countries() ) ); - // Default Locale Can be filtered to override fields in get_address_fields(). - // Countries with no specific locale will use default. + // Default Locale Can be filtered to override fields in get_address_fields(). Countries with no specific locale will use default. $this->locale['default'] = apply_filters( 'woocommerce_get_country_locale_default', $this->get_default_address_fields() ); // Filter default AND shop base locales to allow overides via a single function. These will be used when changing countries on the checkout @@ -1027,6 +1079,7 @@ class WC_Countries { 'class' => array( 'form-row-first' ), 'validate' => array( 'phone' ), 'autocomplete' => 'tel', + 'sort' => 100, ); $address_fields['billing_email'] = array( 'label' => __( 'Email address', 'woocommerce' ), @@ -1036,6 +1089,7 @@ class WC_Countries { 'class' => array( 'form-row-last' ), 'validate' => array( 'email' ), 'autocomplete' => 'no' === get_option( 'woocommerce_registration_generate_username' ) ? 'email' : 'email username', + 'sort' => 110, ); } @@ -1045,8 +1099,6 @@ class WC_Countries { * on country selection. If you want to change things like the required status of an * address field, filter woocommerce_default_address_fields instead. */ - $address_fields = apply_filters( 'woocommerce_' . $type . 'fields', $address_fields, $country ); - - return $address_fields; + return apply_filters( 'woocommerce_' . $type . 'fields', $address_fields, $country ); } } diff --git a/includes/wc-template-functions.php b/includes/wc-template-functions.php index e95e2e5d01b..6272b470a56 100644 --- a/includes/wc-template-functions.php +++ b/includes/wc-template-functions.php @@ -1865,6 +1865,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) { 'validate' => array(), 'default' => '', 'autofocus' => '', + 'sort' => '', ); $args = wp_parse_args( $args, $defaults ); @@ -1913,9 +1914,10 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) { } } - $field = ''; - $label_id = $args['id']; - $field_container = '

%3$s

'; + $field = ''; + $label_id = $args['id']; + $sort = $args['sort'] ? $args['sort'] : ''; + $field_container = '

%3$s

'; switch ( $args['type'] ) { case 'country' : diff --git a/readme.txt b/readme.txt index 7c556454236..2832ae2d671 100644 --- a/readme.txt +++ b/readme.txt @@ -190,6 +190,7 @@ Yes you can! Join in on our [GitHub repository](http://github.com/woocommerce/wo * Added security section in system status report. * Add image_url setting to PayPal Standard. * Fixed attribute registration. Attributes are non-hierarchical by default (parent is not supported). +* Add sort parameter to checkout fields to aid with sorting per locale. * Performance - Converted _featured and _visibility meta data to terms for faster catalog queries. Upgrade routine handles migration. Developers may need to update queries to reflect this change. * Performance - Converted rating filters to visibility terms. * Performance - Added visibility term for outofstock products to speed those queries up also. diff --git a/templates/myaccount/form-edit-address.php b/templates/myaccount/form-edit-address.php index bbbc816ef42..bc72e34dc5e 100644 --- a/templates/myaccount/form-edit-address.php +++ b/templates/myaccount/form-edit-address.php @@ -32,21 +32,23 @@ do_action( 'woocommerce_before_edit_account_address_form' ); ?>

- +
+ - $field ) : ?> + $field ) : ?> - + - + - + -

- - - -

+

+ + + +

+