From f0656e7e38852b9c85f7cec5bb5f4ada738edb86 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Thu, 6 Aug 2015 17:41:12 -0400 Subject: [PATCH 01/63] Tax Rate Search: First whack. This is by no means complete. A number of things need to be relocated and optimized still, but it does a rough search, purely in JS, and highlights the results in yellow. --- .../settings/views/html-settings-tax.php | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index 466b0c5bf9d..f67287e5ceb 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -5,6 +5,44 @@ if ( ! defined( 'ABSPATH' ) ) { ?>

See here for available alpha-2 country codes.', 'woocommerce' ), 'http://en.wikipedia.org/wiki/ISO_3166-1#Current_codes' ); ?>

+ + +

+ + + + From 729e6c924c8373ad0f97a01a7c20f62115eaf257 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Fri, 7 Aug 2015 11:04:55 -0400 Subject: [PATCH 02/63] Big changeover to JS templating for the table. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switching over to building the table with JS — wp.template. We are now using the same JS template for existing rows and newly generated rows on the fly — this should simplify things moving forward. I’ve also started building stuff in an external JS file rather than straight on the page. Will continue migrating things to it and localizing as needed. Saved ( 2 * displayed tax rates - 1 ) db queries per page load by doing the locations all in one query and then parceling them out in php. More coming. --- .../admin/settings_views_html-settings-tax.js | 15 ++ .../settings/views/html-settings-tax.php | 249 +++++++----------- 2 files changed, 110 insertions(+), 154 deletions(-) create mode 100644 assets/js/admin/settings_views_html-settings-tax.js diff --git a/assets/js/admin/settings_views_html-settings-tax.js b/assets/js/admin/settings_views_html-settings-tax.js new file mode 100644 index 00000000000..89866357231 --- /dev/null +++ b/assets/js/admin/settings_views_html-settings-tax.js @@ -0,0 +1,15 @@ +/** + * Used by woocommerce/includes/admin/settings/views/html-settings-tax.php + */ + +(function($, data, wp){ + var rowTemplate = wp.template( 'tax-table-row' ), + $ratesTbody = $('#rates'); + + $(function() { + $ratesTbody.innerHTML = ''; + $.each( data.rates, function ( id, rowData ) { + $ratesTbody.append( rowTemplate( rowData ) ); + } ); + }); +})(jQuery, htmlSettingsTaxLocalizeScript, wp); diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index f67287e5ceb..40493b008e6 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -2,155 +2,71 @@ if ( ! defined( 'ABSPATH' ) ) { exit; } +global $wpdb; + +// Get all the rates and locations. Snagging all at once should significantly cut down on the number of queries. +$rates = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM `{$wpdb->prefix}woocommerce_tax_rates` WHERE `tax_rate_class` = %s ORDER BY `tax_rate_order`;", sanitize_title( $current_class ) ) ); +$locations = $wpdb->get_results( "SELECT * FROM `{$wpdb->prefix}woocommerce_tax_rate_locations`" ); + +// Set the rates keys equal to their ids. +$rates = array_combine( wp_list_pluck( $rates, 'tax_rate_id' ), $rates ); + +// Drop the locations into the rates array. +foreach ( $locations as $location ) { + if ( ! isset( $rates[ $location->tax_rate_id ]->{$location->location_type} ) ) { + $rates[ $location->tax_rate_id ]->{$location->location_type} = array(); + } + $rates[ $location->tax_rate_id ]->{$location->location_type}[] = $location->location_code; +} + +// Localize and enqueue our js. +wp_register_script( 'htmlSettingsTaxLocalizeScript', WC()->plugin_url() . '/assets/js/admin/settings_views_html-settings-tax.js', array( 'jquery', 'wp-util' ), WC_VERSION ); +wp_localize_script( 'htmlSettingsTaxLocalizeScript', 'htmlSettingsTaxLocalizeScript', array( + 'current_class' => $current_class, + 'rates' => $rates, + 'page' => $page, + 'limit' => $limit, + 'strings' => array( + + ), +) ); +wp_enqueue_script( 'htmlSettingsTaxLocalizeScript' ); + ?>

See here for available alpha-2 country codes.', 'woocommerce' ), 'http://en.wikipedia.org/wiki/ISO_3166-1#Current_codes' ); ?>

- - -

- - - -
- - - - - - - - - - - - get_results( $wpdb->prepare( - "SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates - WHERE tax_rate_class = %s - ORDER BY tax_rate_order - LIMIT %d, %d - " , - sanitize_title( $current_class ), - ( $page - 1 ) * $limit, - $limit - ) ); - - foreach ( $rates as $rate ) { - ?> - - - - - - - - - - - - - - - - - - - - - - - + +
  [?] [?] [?] [?] [?] [?] [?] [?] [?]
- - - - - prefix}woocommerce_tax_rate_locations WHERE location_type='postcode' AND tax_rate_id = %d ORDER BY location_code", $rate->tax_rate_id ) ); - - echo esc_attr( implode( '; ', $locations ) ); - ?>" placeholder="*" data-name="tax_rate_postcode[tax_rate_id ?>]" /> - - prefix}woocommerce_tax_rate_locations WHERE location_type='city' AND tax_rate_id = %d ORDER BY location_code", $rate->tax_rate_id ) ); - echo esc_attr( implode( '; ', $locations ) ); - ?>" placeholder="*" data-name="tax_rate_city[tax_rate_id ?>]" /> - - - - - - - - tax_rate_compound, '1' ); ?> /> - - tax_rate_shipping, '1' ); ?> /> -
- @@ -159,7 +75,56 @@ if ( ! defined( 'ABSPATH' ) ) {
+ + + - - From 65eb16fe8a305726e3ea1dcee5985e64b87df962 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Fri, 7 Aug 2015 11:47:39 -0400 Subject: [PATCH 07/63] Migrate csv columns to localize script. --- .../js/admin/settings-views-html-settings-tax.js | 13 +------------ .../admin/settings/views/html-settings-tax.php | 14 +++++++++++++- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index f02869c2f5a..6ca249260e2 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -34,18 +34,7 @@ jQuery('.wc_tax_rates .export').click(function() { - var csv_data = "data:application/csv;charset=utf-8,\n"; + var csv_data = 'data:application/csv;charset=utf-8,' + data.strings.csv_data_cols.join(',') + '\n'; jQuery('#rates tr:visible').each(function() { var row = ''; diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index 8e9b689b0a6..77d598a94f7 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -26,8 +26,20 @@ wp_localize_script( 'wc-settings-tax', 'htmlSettingsTaxLocalizeScript', array( 'page' => $page, 'limit' => $limit, 'strings' => array( - + 'csv_data_cols' => array( + __( 'Country Code', 'woocommerce' ), + __( 'State Code', 'woocommerce' ), + __( 'ZIP/Postcode', 'woocommerce' ), + __( 'City', 'woocommerce' ), + __( 'Rate %', 'woocommerce' ), + __( 'Tax Name', 'woocommerce' ), + __( 'Priority', 'woocommerce' ), + __( 'Compound', 'woocommerce' ), + __( 'Shipping', 'woocommerce' ), + __( 'Tax Class', 'woocommerce' ), + ), ), + ) ); wp_enqueue_script( 'wc-settings-tax' ); From 4221c7be240c5713679a325769ffd90b1e29f5df Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Fri, 7 Aug 2015 11:57:38 -0400 Subject: [PATCH 08/63] Extract the autocomplete for states and countries data. Localize it! --- .../admin/settings-views-html-settings-tax.js | 19 ++---------------- .../settings/views/html-settings-tax.php | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 6ca249260e2..77a470eb46a 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -101,28 +101,13 @@ jQuery(this).attr( 'name', jQuery(this).attr( 'data-name' ) ); }); - var availableCountries = [countries->get_allowed_countries() as $value => $label ) - $countries[] = '{ label: "' . esc_attr( $label ) . '", value: "' . $value . '" }'; - echo implode( ', ', $countries ); - ?>]; - - var availableStates = [countries->get_allowed_country_states() as $value => $label ) - foreach ( $label as $code => $state ) - $countries[] = '{ label: "' . esc_attr( $state ) . '", value: "' . $code . '" }'; - echo implode( ', ', $countries ); - ?>]; - jQuery( "td.country input" ).autocomplete({ - source: availableCountries, + source: data.countries, minLength: 3 }); jQuery( "td.state input" ).autocomplete({ - source: availableStates, + source: data.states, minLength: 3 }); })(jQuery, htmlSettingsTaxLocalizeScript, wp); diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index 77d598a94f7..2c90470dab9 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -19,12 +19,32 @@ foreach ( $locations as $location ) { $rates[ $location->tax_rate_id ]->{$location->location_type}[] = $location->location_code; } +$countries = array(); +foreach ( WC()->countries->get_allowed_countries() as $value => $label ) { + $countries[] = array( + 'label' => $label, + 'value' => $value, + ); +} + +$states = array(); +foreach ( WC()->countries->get_allowed_country_states() as $label ) { + foreach ( $label as $code => $state ) { + $states[] = array( + 'label' => $state, + 'value' => $code, + ); + } +} + // Localize and enqueue our js. wp_localize_script( 'wc-settings-tax', 'htmlSettingsTaxLocalizeScript', array( 'current_class' => $current_class, 'rates' => $rates, 'page' => $page, 'limit' => $limit, + 'countries' => $countries, + 'states' => $states, 'strings' => array( 'csv_data_cols' => array( __( 'Country Code', 'woocommerce' ), From bd30def6a1a1be5907ab0070bc1d347dddd57c03 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Fri, 7 Aug 2015 11:57:48 -0400 Subject: [PATCH 09/63] Whitespace tidy! --- includes/admin/settings/views/html-settings-tax.php | 1 - 1 file changed, 1 deletion(-) diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index 2c90470dab9..974e68c589c 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -59,7 +59,6 @@ wp_localize_script( 'wc-settings-tax', 'htmlSettingsTaxLocalizeScript', array( __( 'Tax Class', 'woocommerce' ), ), ), - ) ); wp_enqueue_script( 'wc-settings-tax' ); From b0309275903f417c082b857aa1c5c11a650f313a Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Fri, 7 Aug 2015 11:58:02 -0400 Subject: [PATCH 10/63] Extract 'No Rows Selected' string --- assets/js/admin/settings-views-html-settings-tax.js | 2 +- includes/admin/settings/views/html-settings-tax.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 77a470eb46a..46346bf09a1 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -27,7 +27,7 @@ jQuery(this).hide(); }); } else { - alert(''); + alert( data.strings.no_rows_selected ); } return false; }); diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index 974e68c589c..aad30d89eaf 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -46,6 +46,7 @@ wp_localize_script( 'wc-settings-tax', 'htmlSettingsTaxLocalizeScript', array( 'countries' => $countries, 'states' => $states, 'strings' => array( + 'no_rows_selected' => __( 'No row(s) selected', 'woocommerce' ), 'csv_data_cols' => array( __( 'Country Code', 'woocommerce' ), __( 'State Code', 'woocommerce' ), From c4768e5274ad892276ae1ad985f9d4e1d6983ce4 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Fri, 7 Aug 2015 11:58:16 -0400 Subject: [PATCH 11/63] Migrate current_class from php to js --- assets/js/admin/settings-views-html-settings-tax.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 46346bf09a1..a10dc3d9ee5 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -58,7 +58,7 @@ row = row + val + ','; }); - row = row + ''; + row = row + data.current_class; //row.substring( 0, row.length - 1 ); csv_data = csv_data + row + "\n"; }); From 9ae32254f2820690443d970bdc97d12e67c706e6 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Fri, 7 Aug 2015 12:00:22 -0400 Subject: [PATCH 12/63] Swap `jQuery` to `$` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s more readable, and safe to do as we’ve aliased it back in the enclosure. --- .../admin/settings-views-html-settings-tax.js | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index a10dc3d9ee5..5f04943bf15 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -13,18 +13,18 @@ } ); }); - jQuery('.wc_tax_rates .remove_tax_rates').click(function() { - var $tbody = jQuery('.wc_tax_rates').find('tbody'); + $('.wc_tax_rates .remove_tax_rates').click(function() { + var $tbody = $('.wc_tax_rates').find('tbody'); if ( $tbody.find('tr.current').size() > 0 ) { $current = $tbody.find('tr.current'); $current.find('input').val(''); $current.find('input.remove_tax_rate').val('1'); $current.each(function(){ - if ( jQuery(this).is('.new') ) - jQuery(this).remove(); + if ( $(this).is('.new') ) + $(this).remove(); else - jQuery(this).hide(); + $(this).hide(); }); } else { alert( data.strings.no_rows_selected ); @@ -32,17 +32,17 @@ return false; }); - jQuery('.wc_tax_rates .export').click(function() { + $('.wc_tax_rates .export').click(function() { var csv_data = 'data:application/csv;charset=utf-8,' + data.strings.csv_data_cols.join(',') + '\n'; - jQuery('#rates tr:visible').each(function() { + $('#rates tr:visible').each(function() { var row = ''; - jQuery(this).find('td:not(.sort) input').each(function() { + $(this).find('td:not(.sort) input').each(function() { - if ( jQuery(this).is('.checkbox') ) { + if ( $(this).is('.checkbox') ) { - if ( jQuery(this).is(':checked') ) { + if ( $(this).is(':checked') ) { val = 1; } else { val = 0; @@ -50,10 +50,10 @@ } else { - var val = jQuery(this).val(); + var val = $(this).val(); if ( ! val ) - val = jQuery(this).attr('placeholder'); + val = $(this).attr('placeholder'); } row = row + val + ','; @@ -63,13 +63,13 @@ csv_data = csv_data + row + "\n"; }); - jQuery(this).attr( 'href', encodeURI( csv_data ) ); + $(this).attr( 'href', encodeURI( csv_data ) ); return true; }); - jQuery('.wc_tax_rates .insert').click(function() { - var $tbody = jQuery('.wc_tax_rates').find('tbody'); + $('.wc_tax_rates .insert').click(function() { + var $tbody = $('.wc_tax_rates').find('tbody'); var size = $tbody.find('tr').size(); var code = wp.template( 'wc-tax-table-row' )( { tax_rate_id : 'new-' + size, @@ -84,12 +84,12 @@ $tbody.append( code ); } - jQuery( "td.country input" ).autocomplete({ + $( "td.country input" ).autocomplete({ source: availableCountries, minLength: 3 }); - jQuery( "td.state input" ).autocomplete({ + $( "td.state input" ).autocomplete({ source: availableStates, minLength: 3 }); @@ -97,16 +97,16 @@ return false; }); - jQuery('.wc_tax_rates td.postcode, .wc_tax_rates td.city').find('input').change(function() { - jQuery(this).attr( 'name', jQuery(this).attr( 'data-name' ) ); + $('.wc_tax_rates td.postcode, .wc_tax_rates td.city').find('input').change(function() { + $(this).attr( 'name', $(this).attr( 'data-name' ) ); }); - jQuery( "td.country input" ).autocomplete({ + $( "td.country input" ).autocomplete({ source: data.countries, minLength: 3 }); - jQuery( "td.state input" ).autocomplete({ + $( "td.state input" ).autocomplete({ source: data.states, minLength: 3 }); From 69b6936d4d53f4a065622cc3f756658dba403cf3 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Fri, 7 Aug 2015 12:01:40 -0400 Subject: [PATCH 13/63] Don't constantly rescan the dom for tbody We have a cached version of $tbody a level up. --- assets/js/admin/settings-views-html-settings-tax.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 5f04943bf15..e3455f9b80d 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -14,7 +14,6 @@ }); $('.wc_tax_rates .remove_tax_rates').click(function() { - var $tbody = $('.wc_tax_rates').find('tbody'); if ( $tbody.find('tr.current').size() > 0 ) { $current = $tbody.find('tr.current'); $current.find('input').val(''); @@ -69,7 +68,6 @@ }); $('.wc_tax_rates .insert').click(function() { - var $tbody = $('.wc_tax_rates').find('tbody'); var size = $tbody.find('tr').size(); var code = wp.template( 'wc-tax-table-row' )( { tax_rate_id : 'new-' + size, From 516977bd01b95a02e718231cf818cf5bf100c04f Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Fri, 7 Aug 2015 12:10:01 -0400 Subject: [PATCH 14/63] JSHint fixes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The other advantage of splitting js out of php files — jshint can run on it! :) :) :) --- .../admin/settings-views-html-settings-tax.js | 43 +++++++++---------- .../settings/views/html-settings-tax.php | 2 +- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index e3455f9b80d..d0bd86c18af 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -1,3 +1,4 @@ +/* global htmlSettingsTaxLocalizeScript */ /** * Used by woocommerce/includes/admin/settings/views/html-settings-tax.php */ @@ -15,18 +16,19 @@ $('.wc_tax_rates .remove_tax_rates').click(function() { if ( $tbody.find('tr.current').size() > 0 ) { - $current = $tbody.find('tr.current'); + var $current = $tbody.find('tr.current'); $current.find('input').val(''); $current.find('input.remove_tax_rate').val('1'); $current.each(function(){ - if ( $(this).is('.new') ) - $(this).remove(); - else - $(this).hide(); + if ( $(this).is('.new') ) { + $( this ).remove(); + } else { + $( this ).hide(); + } }); } else { - alert( data.strings.no_rows_selected ); + window.alert( data.strings.no_rows_selected ); } return false; }); @@ -38,28 +40,25 @@ $('#rates tr:visible').each(function() { var row = ''; $(this).find('td:not(.sort) input').each(function() { + var val = ''; if ( $(this).is('.checkbox') ) { - if ( $(this).is(':checked') ) { val = 1; } else { val = 0; } - } else { - - var val = $(this).val(); - - if ( ! val ) - val = $(this).attr('placeholder'); + val = $(this).val(); + if ( ! val ) { + val = $( this ).attr( 'placeholder' ); + } } - row = row + val + ','; }); row = row + data.current_class; //row.substring( 0, row.length - 1 ); - csv_data = csv_data + row + "\n"; + csv_data = csv_data + row + '\n'; }); $(this).attr( 'href', encodeURI( csv_data ) ); @@ -73,7 +72,7 @@ tax_rate_id : 'new-' + size, tax_rate_priority : 1, tax_rate_shipping : 1, - new : true + newRow : true } ); if ( $tbody.find('tr.current').size() > 0 ) { @@ -82,13 +81,13 @@ $tbody.append( code ); } - $( "td.country input" ).autocomplete({ - source: availableCountries, + $( 'td.country input' ).autocomplete({ + source: data.countries, minLength: 3 }); - $( "td.state input" ).autocomplete({ - source: availableStates, + $( 'td.state input' ).autocomplete({ + source: data.states, minLength: 3 }); @@ -99,12 +98,12 @@ $(this).attr( 'name', $(this).attr( 'data-name' ) ); }); - $( "td.country input" ).autocomplete({ + $( 'td.country input' ).autocomplete({ source: data.countries, minLength: 3 }); - $( "td.state input" ).autocomplete({ + $( 'td.state input' ).autocomplete({ source: data.states, minLength: 3 }); diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index aad30d89eaf..f047d664402 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -113,7 +113,7 @@ wp_enqueue_script( 'wc-settings-tax' ); + + \ No newline at end of file From 5736d66a92974bdce2dcae0400f042357040ce73 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Fri, 7 Aug 2015 16:58:42 -0400 Subject: [PATCH 28/63] Pagination now works by first, prev, next, last. Still need to get number based pagination working. --- .../admin/settings-views-html-settings-tax.js | 51 ++++++++++++++----- .../settings/views/html-settings-tax.php | 8 +-- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index fb6ce55039a..8cdfffc5a32 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -8,7 +8,8 @@ var rowTemplate = wp.template( 'wc-tax-table-row' ), paginationTemplate = wp.template( 'wc-tax-table-pagination' ), - $tbody = $('#rates'); + $tbody = $('#rates' ), + $pagination = $( '#rates-pagination' ); /** * Build the table contents. @@ -42,24 +43,48 @@ } /** - * Handle the initial display. + * Renders table contents by page. */ - if ( data.rates.length <= data.limit ) { - renderTableContents( data.rates ); - } else { - var first_index = data.limit * ( data.page - 1), - last_index = data.limit * data.page; + function renderPage( page_num ) { + var qty_pages = Math.ceil( data.rates.length / data.limit ); + + page_num = parseInt( page_num, 10 ); + if ( page_num < 1 ) { + page_num = 1; + } else if ( page_num > qty_pages ) { + page_num = qty_pages; + } + + var first_index = data.limit * ( page_num - 1), + last_index = data.limit * page_num; renderTableContents( data.rates.slice( first_index, last_index ) ); - // We've now displayed our initial page, time to render the pagination box. - $('#rates-pagination' ).html( paginationTemplate( { - qty_rates : data.rates.length, - current_page : data.page, - qty_pages : Math.ceil( data.rates.length / data.limit ) - } ) ); + if ( data.rates.length > data.limit ) { + // We've now displayed our initial page, time to render the pagination box. + $pagination.html( paginationTemplate( { + qty_rates : data.rates.length, + current_page : page_num, + qty_pages : qty_pages + } ) ); + } } + /** + * Handle the initial display. + */ + renderPage( data.page ); + + /** + * Handle clicks on the pagination links. + * + * Abstracting it out here instead of re-running it after each render. + */ + $pagination.on( 'click', 'a', function(event){ + event.preventDefault(); + renderPage( $( event.currentTarget ).data('goto') ); + } ); + $('.wc_tax_rates .remove_tax_rates').click(function() { if ( $tbody.find('tr.current').length > 0 ) { var $current = $tbody.find('tr.current'); diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index 5957595e307..b328fb935ff 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -173,11 +173,11 @@ wp_enqueue_script( 'wc-settings-tax' ); - + - + @@ -189,11 +189,11 @@ wp_enqueue_script( 'wc-settings-tax' ); '{{ data.qty_pages }}' ); ?> - + - + From bba6f80d9d47350e4dd348bb57221302083ebc25 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Fri, 7 Aug 2015 17:06:50 -0400 Subject: [PATCH 29/63] Don't set them for unexistent rates. --- includes/admin/settings/views/html-settings-tax.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index b328fb935ff..49abe0aa01f 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -13,6 +13,11 @@ $rates = array_combine( wp_list_pluck( $rates, 'tax_rate_id' ), $rates ); // Drop the locations into the rates array. foreach ( $locations as $location ) { + // Don't set them for unexistent rates. + if ( ! isset( $rates[ $location->tax_rate_id ] ) ) { + continue; + } + // If the rate exists, initialize the array before appending to it. if ( ! isset( $rates[ $location->tax_rate_id ]->{$location->location_type} ) ) { $rates[ $location->tax_rate_id ]->{$location->location_type} = array(); } From c2d5e3c5a07d84109adcd81f32487429a7c54d5c Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Fri, 7 Aug 2015 17:21:44 -0400 Subject: [PATCH 30/63] Update the current page when the number is changed. --- assets/js/admin/settings-views-html-settings-tax.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 8cdfffc5a32..4f29d7f92c1 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -84,6 +84,9 @@ event.preventDefault(); renderPage( $( event.currentTarget ).data('goto') ); } ); + $pagination.on( 'change', 'input', function(event) { + renderPage( $( event.currentTarget ).val() ); + } ); $('.wc_tax_rates .remove_tax_rates').click(function() { if ( $tbody.find('tr.current').length > 0 ) { From d854e8dc2a54943dda6b159f9d3fa4a61b4f2f26 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Fri, 7 Aug 2015 17:22:07 -0400 Subject: [PATCH 31/63] Remove the legacy pagination. --- .../admin/settings/views/html-settings-tax.php | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index 49abe0aa01f..46052fd9f31 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -99,21 +99,6 @@ wp_enqueue_script( 'wc-settings-tax' ); - - From 521d8f48619e6a89be43eb69a5366a8f007a12f2 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Fri, 7 Aug 2015 17:28:44 -0400 Subject: [PATCH 32/63] Migrate the logic and queries out of the template file. Move them where they belong, in the class that calls it. --- .../admin/settings/class-wc-settings-tax.php | 66 ++++++++++++++++++- .../settings/views/html-settings-tax.php | 66 ------------------- 2 files changed, 64 insertions(+), 68 deletions(-) diff --git a/includes/admin/settings/class-wc-settings-tax.php b/includes/admin/settings/class-wc-settings-tax.php index c05a404ee6e..946fa1518ef 100644 --- a/includes/admin/settings/class-wc-settings-tax.php +++ b/includes/admin/settings/class-wc-settings-tax.php @@ -106,10 +106,72 @@ class WC_Settings_Tax extends WC_Settings_Page { public function output_tax_rates() { global $wpdb; - $page = ! empty( $_GET['p'] ) ? absint( $_GET['p'] ) : 1; - $limit = 100; $current_class = $this->get_current_tax_class(); + // Get all the rates and locations. Snagging all at once should significantly cut down on the number of queries. + $rates = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM `{$wpdb->prefix}woocommerce_tax_rates` WHERE `tax_rate_class` = %s ORDER BY `tax_rate_order`;", sanitize_title( $current_class ) ) ); + $locations = $wpdb->get_results( "SELECT * FROM `{$wpdb->prefix}woocommerce_tax_rate_locations`" ); + + // Set the rates keys equal to their ids. + $rates = array_combine( wp_list_pluck( $rates, 'tax_rate_id' ), $rates ); + + // Drop the locations into the rates array. + foreach ( $locations as $location ) { + // Don't set them for unexistent rates. + if ( ! isset( $rates[ $location->tax_rate_id ] ) ) { + continue; + } + // If the rate exists, initialize the array before appending to it. + if ( ! isset( $rates[ $location->tax_rate_id ]->{$location->location_type} ) ) { + $rates[ $location->tax_rate_id ]->{$location->location_type} = array(); + } + $rates[ $location->tax_rate_id ]->{$location->location_type}[] = $location->location_code; + } + + $countries = array(); + foreach ( WC()->countries->get_allowed_countries() as $value => $label ) { + $countries[] = array( + 'label' => $label, + 'value' => $value, + ); + } + + $states = array(); + foreach ( WC()->countries->get_allowed_country_states() as $label ) { + foreach ( $label as $code => $state ) { + $states[] = array( + 'label' => $state, + 'value' => $code, + ); + } + } + + // Localize and enqueue our js. + wp_localize_script( 'wc-settings-tax', 'htmlSettingsTaxLocalizeScript', array( + 'current_class' => $current_class, + 'rates' => array_values( $rates ), + 'page' => ! empty( $_GET['p'] ) ? absint( $_GET['p'] ) : 1, + 'limit' => 100, + 'countries' => $countries, + 'states' => $states, + 'strings' => array( + 'no_rows_selected' => __( 'No row(s) selected', 'woocommerce' ), + 'csv_data_cols' => array( + __( 'Country Code', 'woocommerce' ), + __( 'State Code', 'woocommerce' ), + __( 'ZIP/Postcode', 'woocommerce' ), + __( 'City', 'woocommerce' ), + __( 'Rate %', 'woocommerce' ), + __( 'Tax Name', 'woocommerce' ), + __( 'Priority', 'woocommerce' ), + __( 'Compound', 'woocommerce' ), + __( 'Shipping', 'woocommerce' ), + __( 'Tax Class', 'woocommerce' ), + ), + ), + ) ); + wp_enqueue_script( 'wc-settings-tax' ); + include( 'views/html-settings-tax.php' ); } diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index 46052fd9f31..0a6f29260a5 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -2,72 +2,6 @@ if ( ! defined( 'ABSPATH' ) ) { exit; } -global $wpdb; - -// Get all the rates and locations. Snagging all at once should significantly cut down on the number of queries. -$rates = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM `{$wpdb->prefix}woocommerce_tax_rates` WHERE `tax_rate_class` = %s ORDER BY `tax_rate_order`;", sanitize_title( $current_class ) ) ); -$locations = $wpdb->get_results( "SELECT * FROM `{$wpdb->prefix}woocommerce_tax_rate_locations`" ); - -// Set the rates keys equal to their ids. -$rates = array_combine( wp_list_pluck( $rates, 'tax_rate_id' ), $rates ); - -// Drop the locations into the rates array. -foreach ( $locations as $location ) { - // Don't set them for unexistent rates. - if ( ! isset( $rates[ $location->tax_rate_id ] ) ) { - continue; - } - // If the rate exists, initialize the array before appending to it. - if ( ! isset( $rates[ $location->tax_rate_id ]->{$location->location_type} ) ) { - $rates[ $location->tax_rate_id ]->{$location->location_type} = array(); - } - $rates[ $location->tax_rate_id ]->{$location->location_type}[] = $location->location_code; -} - -$countries = array(); -foreach ( WC()->countries->get_allowed_countries() as $value => $label ) { - $countries[] = array( - 'label' => $label, - 'value' => $value, - ); -} - -$states = array(); -foreach ( WC()->countries->get_allowed_country_states() as $label ) { - foreach ( $label as $code => $state ) { - $states[] = array( - 'label' => $state, - 'value' => $code, - ); - } -} - -// Localize and enqueue our js. -wp_localize_script( 'wc-settings-tax', 'htmlSettingsTaxLocalizeScript', array( - 'current_class' => $current_class, - 'rates' => array_values( $rates ), - 'page' => $page, - 'limit' => $limit, - 'countries' => $countries, - 'states' => $states, - 'strings' => array( - 'no_rows_selected' => __( 'No row(s) selected', 'woocommerce' ), - 'csv_data_cols' => array( - __( 'Country Code', 'woocommerce' ), - __( 'State Code', 'woocommerce' ), - __( 'ZIP/Postcode', 'woocommerce' ), - __( 'City', 'woocommerce' ), - __( 'Rate %', 'woocommerce' ), - __( 'Tax Name', 'woocommerce' ), - __( 'Priority', 'woocommerce' ), - __( 'Compound', 'woocommerce' ), - __( 'Shipping', 'woocommerce' ), - __( 'Tax Class', 'woocommerce' ), - ), - ), -) ); -wp_enqueue_script( 'wc-settings-tax' ); - ?>

From 9946bd1c5c209af622f8383a70dfdc050c81b4f8 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Sat, 8 Aug 2015 10:57:03 -0400 Subject: [PATCH 33/63] Retool the export to use the global object, not parsing out of the dom. --- .../admin/settings-views-html-settings-tax.js | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 4f29d7f92c1..5edc340c538 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -108,35 +108,28 @@ }); /** - * Handle the exporting of tax rates. + * Handle the exporting of tax rates, and build it off the global `data.rates` object. * - * As an aside: Why is this being handled in Javascript instead of being built by php? -George + * @todo: Have the `export` button save the current form and generate this from php, so there's no chance the current page is out of date. */ $('.wc_tax_rates .export').click(function() { var csv_data = 'data:application/csv;charset=utf-8,' + data.strings.csv_data_cols.join(',') + '\n'; - $('#rates tr:visible').each(function() { + $.each( data.rates, function( id, rowData ) { var row = ''; - $(this).find('td:not(.sort) input').each(function() { - var val = ''; - if ( $(this).is('.checkbox') ) { - if ( $(this).is(':checked') ) { - val = 1; - } else { - val = 0; - } - } else { - val = $(this).val(); - if ( ! val ) { - val = $( this ).attr( 'placeholder' ); - } - } - row = row + val + ','; - }); - row = row + data.current_class; - //row.substring( 0, row.length - 1 ); - csv_data = csv_data + row + '\n'; + row += rowData.tax_rate_country + ','; + row += rowData.tax_rate_state + ','; + row += rowData.tax_rate_postcode ? rowData.tax_rate_postcode.join( '; ' ) : '' + ','; + row += rowData.tax_rate_city ? rowData.tax_rate_city.join( '; ' ) : '' + ','; + row += rowData.tax_rate + ','; + row += rowData.tax_rate_name + ','; + row += rowData.tax_rate_priority + ','; + row += rowData.tax_rate_compound + ','; + row += rowData.tax_rate_shipping + ','; + row += data.current_class; + + csv_data += row + '\n'; }); $(this).attr( 'href', encodeURI( csv_data ) ); From 7c5d05d29d7549e78ef96a984150ea160774eb9f Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Sat, 8 Aug 2015 10:57:22 -0400 Subject: [PATCH 34/63] Whitespace tweaks. --- assets/js/admin/settings-views-html-settings-tax.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 5edc340c538..4984abd9e18 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -6,10 +6,10 @@ (function($, data, wp){ $(function() { - var rowTemplate = wp.template( 'wc-tax-table-row' ), + var rowTemplate = wp.template( 'wc-tax-table-row' ), paginationTemplate = wp.template( 'wc-tax-table-pagination' ), - $tbody = $('#rates' ), - $pagination = $( '#rates-pagination' ); + $tbody = $( '#rates' ), + $pagination = $( '#rates-pagination' ); /** * Build the table contents. @@ -22,7 +22,7 @@ // Populate $tbody with the current page of results. $.each( rates, function ( id, rowData ) { $tbody.append( rowTemplate( rowData ) ); - } ); + }); // Initialize autocomplete for countries. $tbody.find( 'td.country input' ).autocomplete({ From d2e4f31042ed0ae651572019ec397780e69f37ef Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Sat, 8 Aug 2015 10:57:46 -0400 Subject: [PATCH 35/63] Optimization, save the $table selector to avoid some dom lookups. --- assets/js/admin/settings-views-html-settings-tax.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 4984abd9e18..0ecad3201f3 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -8,6 +8,7 @@ var rowTemplate = wp.template( 'wc-tax-table-row' ), paginationTemplate = wp.template( 'wc-tax-table-pagination' ), + $table = $( '.wc_tax_rates' ); $tbody = $( '#rates' ), $pagination = $( '#rates-pagination' ); @@ -88,7 +89,7 @@ renderPage( $( event.currentTarget ).val() ); } ); - $('.wc_tax_rates .remove_tax_rates').click(function() { + $table.find('.remove_tax_rates').click(function() { if ( $tbody.find('tr.current').length > 0 ) { var $current = $tbody.find('tr.current'); $current.find('input').val(''); @@ -112,7 +113,7 @@ * * @todo: Have the `export` button save the current form and generate this from php, so there's no chance the current page is out of date. */ - $('.wc_tax_rates .export').click(function() { + $table.find('.export').click(function() { var csv_data = 'data:application/csv;charset=utf-8,' + data.strings.csv_data_cols.join(',') + '\n'; $.each( data.rates, function( id, rowData ) { @@ -140,7 +141,7 @@ /** * Add a new blank row to the table for the user to fill out and save. */ - $('.wc_tax_rates .insert').click(function() { + $table.find('.insert').click(function() { var size = $tbody.find('tr').length; var code = wp.template( 'wc-tax-table-row' )( { tax_rate_id : 'new-' + size, From f9331ab5c492493e1e8ba22e7fbc465b2b8caf77 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Sat, 8 Aug 2015 11:03:46 -0400 Subject: [PATCH 36/63] Should be comparing to `'1'` not `1`. --- includes/admin/settings/views/html-settings-tax.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index 0a6f29260a5..f035c637f99 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -82,11 +82,11 @@ if ( ! defined( 'ABSPATH' ) ) { - checked="checked" <# } #> /> + checked="checked" <# } #> /> - checked="checked" <# } #> /> + checked="checked" <# } #> /> From e0d9ff88917e7edb5134b2c5a03789bbfaae31c1 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Sat, 8 Aug 2015 14:45:21 -0400 Subject: [PATCH 37/63] Set backbone and underscore as script dependencies. --- includes/admin/class-wc-admin-assets.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin/class-wc-admin-assets.php b/includes/admin/class-wc-admin-assets.php index 0655d59feec..9c268a725f7 100644 --- a/includes/admin/class-wc-admin-assets.php +++ b/includes/admin/class-wc-admin-assets.php @@ -91,7 +91,7 @@ class WC_Admin_Assets { wp_register_script( 'qrcode', WC()->plugin_url() . '/assets/js/jquery-qrcode/jquery.qrcode' . $suffix . '.js', array( 'jquery' ), WC_VERSION ); wp_register_script( 'stupidtable', WC()->plugin_url() . '/assets/js/stupidtable/stupidtable' . $suffix . '.js', array( 'jquery' ), WC_VERSION ); wp_register_script( 'serializejson', WC()->plugin_url() . '/assets/js/jquery-serializejson/jquery.serializejson' . $suffix . '.js', array( 'jquery' ), '2.6.1' ); - wp_register_script( 'wc-settings-tax', WC()->plugin_url() . '/assets/js/admin/settings-views-html-settings-tax.js', array( 'jquery', 'wp-util' ), WC_VERSION ); + wp_register_script( 'wc-settings-tax', WC()->plugin_url() . '/assets/js/admin/settings-views-html-settings-tax.js', array( 'jquery', 'wp-util', 'underscore', 'backbone' ), WC_VERSION ); // Chosen is @deprecated (2.3) in favour of select2, but is registered for backwards compat wp_register_script( 'ajax-chosen', WC()->plugin_url() . '/assets/js/chosen/ajax-chosen.jquery' . $suffix . '.js', array( 'jquery', 'chosen' ), WC_VERSION ); From 9c0af3c7ff115b6a9032e719870d14d3c09c87cc Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Sat, 8 Aug 2015 14:45:37 -0400 Subject: [PATCH 38/63] Whoops! Comma, not semicolon. --- assets/js/admin/settings-views-html-settings-tax.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 0ecad3201f3..9b375742390 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -8,7 +8,7 @@ var rowTemplate = wp.template( 'wc-tax-table-row' ), paginationTemplate = wp.template( 'wc-tax-table-pagination' ), - $table = $( '.wc_tax_rates' ); + $table = $( '.wc_tax_rates' ), $tbody = $( '#rates' ), $pagination = $( '#rates-pagination' ); From 9c5a35762bd503eda2a93bb22c900a63cf7780b3 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Sat, 8 Aug 2015 14:46:21 -0400 Subject: [PATCH 39/63] Change the structure to Backbone models/views. --- .../admin/settings-views-html-settings-tax.js | 119 ++++++++++-------- 1 file changed, 65 insertions(+), 54 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 9b375742390..315e2bc9fee 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -10,66 +10,77 @@ paginationTemplate = wp.template( 'wc-tax-table-pagination' ), $table = $( '.wc_tax_rates' ), $tbody = $( '#rates' ), - $pagination = $( '#rates-pagination' ); + $pagination = $( '#rates-pagination' ), + WCTaxTableModelConstructor = Backbone.Model.extend( {} ), + WCTaxTableViewConstructor = Backbone.View.extend({ + rowTemplate : rowTemplate, + per_page : data.limit, + page : data.page, + render : function() { + var rates = this.model.get( 'rates' ), + qty_rates = rates.length, + qty_pages = Math.ceil( qty_rates / this.per_page ), + first_index = this.per_page * ( this.page - 1), + last_index = this.per_page * this.page, + paged_rates = rates.slice( first_index, last_index ), + view = this; - /** - * Build the table contents. - * @param rates - */ - function renderTableContents( rates ) { - // Blank out the contents. - $tbody.empty(); + // Blank out the contents. + this.$el.empty(); - // Populate $tbody with the current page of results. - $.each( rates, function ( id, rowData ) { - $tbody.append( rowTemplate( rowData ) ); - }); + // Populate $tbody with the current page of results. + $.each( paged_rates, function ( id, rowData ) { + view.$el.append( view.rowTemplate( rowData ) ); + }); - // Initialize autocomplete for countries. - $tbody.find( 'td.country input' ).autocomplete({ - source: data.countries, - minLength: 3 - }); + // Initialize autocomplete for countries. + this.$el.find( 'td.country input' ).autocomplete({ + source: data.countries, + minLength: 3 + }); - // Initialize autocomplete for states. - $tbody.find( 'td.state input' ).autocomplete({ - source: data.states, - minLength: 3 - }); + // Initialize autocomplete for states. + this.$el.find( 'td.state input' ).autocomplete({ + source: data.states, + minLength: 3 + }); - // Postcode and city don't have `name` values by default. They're only created if the contents changes, to save on database queries (I think) - $tbody.find( 'td.postcode input, td.city input').change(function() { - $(this).attr( 'name', $(this).data( 'name' ) ); - }); - } + // Postcode and city don't have `name` values by default. They're only created if the contents changes, to save on database queries (I think) + this.$el.find( 'td.postcode input, td.city input' ).change(function() { + $(this).attr( 'name', $(this).data( 'name' ) ); + }); - /** - * Renders table contents by page. - */ - function renderPage( page_num ) { - var qty_pages = Math.ceil( data.rates.length / data.limit ); - - page_num = parseInt( page_num, 10 ); - if ( page_num < 1 ) { - page_num = 1; - } else if ( page_num > qty_pages ) { - page_num = qty_pages; - } - - var first_index = data.limit * ( page_num - 1), - last_index = data.limit * page_num; - - renderTableContents( data.rates.slice( first_index, last_index ) ); - - if ( data.rates.length > data.limit ) { - // We've now displayed our initial page, time to render the pagination box. - $pagination.html( paginationTemplate( { - qty_rates : data.rates.length, - current_page : page_num, - qty_pages : qty_pages - } ) ); - } - } + if ( qty_pages > 1 ) { + // We've now displayed our initial page, time to render the pagination box. + $pagination.html( paginationTemplate( { + qty_rates : qty_rates, + current_page : this.page, + qty_pages : qty_pages + } ) ); + } + }, + initialize : function() { + this.qty_pages = Math.ceil( this.model.get( 'rates' ).length / this.per_page ); + }, + sanitizePage : function( page_num ) { + page_num = parseInt( page_num, 10 ); + if ( page_num < 1 ) { + page_num = 1; + } else if ( page_num > this.qty_pages ) { + page_num = this.qty_pages; + } + return page_num; + } + } ), + WCTaxTableModelInstance = new WCTaxTableModelConstructor({ + rates : data.rates, + } ), + WCTaxTableInstance = new WCTaxTableViewConstructor({ + model : WCTaxTableModelInstance, + // page : data.page, // I'd prefer to have these two specified down here in the instance, + // per_page : data.limit, // but it doesn't seem to recognize them in render if I do. :\ + el : '#rates' + } ); /** * Handle the initial display. From 29df63b76756f3d15b94b74b0b4fe3e1c15140e0 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Sat, 8 Aug 2015 14:46:37 -0400 Subject: [PATCH 40/63] Change how things are called to the new bb render. --- assets/js/admin/settings-views-html-settings-tax.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 315e2bc9fee..bf66bc215a6 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -82,10 +82,7 @@ el : '#rates' } ); - /** - * Handle the initial display. - */ - renderPage( data.page ); + WCTaxTableInstance.render(); /** * Handle clicks on the pagination links. @@ -94,10 +91,12 @@ */ $pagination.on( 'click', 'a', function(event){ event.preventDefault(); - renderPage( $( event.currentTarget ).data('goto') ); + WCTaxTableInstance.page = WCTaxTableInstance.sanitizePage( $( event.currentTarget ).data('goto') ); + WCTaxTableInstance.render(); } ); $pagination.on( 'change', 'input', function(event) { - renderPage( $( event.currentTarget ).val() ); + WCTaxTableInstance.page = WCTaxTableInstance.sanitizePage( $( event.currentTarget ).val() ); + WCTaxTableInstance.render(); } ); $table.find('.remove_tax_rates').click(function() { From 6b76f81786dd6b6aa513cb675b25779adc161950 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 10:29:11 -0400 Subject: [PATCH 41/63] Add a `beforeunload` event to prompt before leaving with unsaved changes. --- .../admin/settings-views-html-settings-tax.js | 18 ++++++++++++++++++ .../admin/settings/class-wc-settings-tax.php | 1 + 2 files changed, 19 insertions(+) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index bf66bc215a6..88c028ba8c8 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -61,6 +61,24 @@ }, initialize : function() { this.qty_pages = Math.ceil( this.model.get( 'rates' ).length / this.per_page ); + this.listenTo( this.model, 'change', this.setUnloadConfirmation ); + this.listenTo( this.model, 'saved', this.clearUnloadConfirmation ); + window.addEventListener( 'beforeunload', this.unloadConfirmation ); + }, + setUnloadConfirmation : function() { + console.log( data.strings.unload_confirmation_msg ); + this.needsUnloadConfirm = true; + }, + clearUnloadConfirmation : function() { + this.needsUnloadConfirm = false; + }, + unloadConfirmation : function(e) { + if ( this.needsUnloadConfirm ) { + e.returnValue = data.strings.unload_confirmation_msg; + window.event.returnValue = data.strings.unload_confirmation_msg; + return data.strings.unload_confirmation_msg; + } + return null; }, sanitizePage : function( page_num ) { page_num = parseInt( page_num, 10 ); diff --git a/includes/admin/settings/class-wc-settings-tax.php b/includes/admin/settings/class-wc-settings-tax.php index 946fa1518ef..857558a1958 100644 --- a/includes/admin/settings/class-wc-settings-tax.php +++ b/includes/admin/settings/class-wc-settings-tax.php @@ -156,6 +156,7 @@ class WC_Settings_Tax extends WC_Settings_Page { 'states' => $states, 'strings' => array( 'no_rows_selected' => __( 'No row(s) selected', 'woocommerce' ), + 'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ), 'csv_data_cols' => array( __( 'Country Code', 'woocommerce' ), __( 'State Code', 'woocommerce' ), From d7b9c2cbe7d30521fb8bb5b63877b26bd0109e2e Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 16:02:15 -0400 Subject: [PATCH 42/63] Remove some debugging --- assets/js/admin/settings-views-html-settings-tax.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 88c028ba8c8..dac88384083 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -66,7 +66,6 @@ window.addEventListener( 'beforeunload', this.unloadConfirmation ); }, setUnloadConfirmation : function() { - console.log( data.strings.unload_confirmation_msg ); this.needsUnloadConfirm = true; }, clearUnloadConfirmation : function() { @@ -78,7 +77,6 @@ window.event.returnValue = data.strings.unload_confirmation_msg; return data.strings.unload_confirmation_msg; } - return null; }, sanitizePage : function( page_num ) { page_num = parseInt( page_num, 10 ); From b16d0f7673da32ac88e87fc5dfc882ec5d923132 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 16:02:32 -0400 Subject: [PATCH 43/63] JS objects + trailing commas = sad IE --- assets/js/admin/settings-views-html-settings-tax.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index dac88384083..11cc3a30be9 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -89,7 +89,7 @@ } } ), WCTaxTableModelInstance = new WCTaxTableModelConstructor({ - rates : data.rates, + rates : data.rates } ), WCTaxTableInstance = new WCTaxTableViewConstructor({ model : WCTaxTableModelInstance, From 1a1a639facc002e0b707d6380073f0b1b79bd0e9 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 16:03:13 -0400 Subject: [PATCH 44/63] =?UTF-8?q?Use=20$(window).on()=20instead=20of=20win?= =?UTF-8?q?dow.addEventListener.=20=20Because=20=C2=AF\=5F(=E3=83=84)=5F/?= =?UTF-8?q?=C2=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/js/admin/settings-views-html-settings-tax.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 11cc3a30be9..f3f1468f855 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -63,7 +63,7 @@ this.qty_pages = Math.ceil( this.model.get( 'rates' ).length / this.per_page ); this.listenTo( this.model, 'change', this.setUnloadConfirmation ); this.listenTo( this.model, 'saved', this.clearUnloadConfirmation ); - window.addEventListener( 'beforeunload', this.unloadConfirmation ); + $(window).on( 'beforeunload', this.unloadConfirmation ); }, setUnloadConfirmation : function() { this.needsUnloadConfirm = true; From ccd1734353e0261d1eefd8cf1d3e470e486b6cc9 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 16:05:49 -0400 Subject: [PATCH 45/63] Don't use `this` in a callback with the wrong context. @todo: Find a way to stop needing to refer to the specific instance from the abstract class. --- assets/js/admin/settings-views-html-settings-tax.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index f3f1468f855..322fdb7c78d 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -72,7 +72,8 @@ this.needsUnloadConfirm = false; }, unloadConfirmation : function(e) { - if ( this.needsUnloadConfirm ) { + // @todo: Find a way to stop needing to refer to the specific instance from the abstract class. + if ( WCTaxTableInstance.needsUnloadConfirm ) { e.returnValue = data.strings.unload_confirmation_msg; window.event.returnValue = data.strings.unload_confirmation_msg; return data.strings.unload_confirmation_msg; From 59a1a313a67ebd259a326983a1432a6920a8f2f4 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 16:23:44 -0400 Subject: [PATCH 46/63] Figured out how to avoid hardcoding the instance. --- assets/js/admin/settings-views-html-settings-tax.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 322fdb7c78d..ba4c5a2a66b 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -63,7 +63,7 @@ this.qty_pages = Math.ceil( this.model.get( 'rates' ).length / this.per_page ); this.listenTo( this.model, 'change', this.setUnloadConfirmation ); this.listenTo( this.model, 'saved', this.clearUnloadConfirmation ); - $(window).on( 'beforeunload', this.unloadConfirmation ); + $(window).on( 'beforeunload', { view : this }, this.unloadConfirmation ); }, setUnloadConfirmation : function() { this.needsUnloadConfirm = true; @@ -72,8 +72,7 @@ this.needsUnloadConfirm = false; }, unloadConfirmation : function(e) { - // @todo: Find a way to stop needing to refer to the specific instance from the abstract class. - if ( WCTaxTableInstance.needsUnloadConfirm ) { + if ( e.data.view.needsUnloadConfirm ) { e.returnValue = data.strings.unload_confirmation_msg; window.event.returnValue = data.strings.unload_confirmation_msg; return data.strings.unload_confirmation_msg; From 73a52e0ade80e72acd6725c860813a111f318143 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 16:27:04 -0400 Subject: [PATCH 47/63] Probably tidier to use `event` and not `e` --- assets/js/admin/settings-views-html-settings-tax.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index ba4c5a2a66b..e9c6da6df59 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -71,9 +71,9 @@ clearUnloadConfirmation : function() { this.needsUnloadConfirm = false; }, - unloadConfirmation : function(e) { - if ( e.data.view.needsUnloadConfirm ) { - e.returnValue = data.strings.unload_confirmation_msg; + unloadConfirmation : function(event) { + if ( event.data.view.needsUnloadConfirm ) { + event.returnValue = data.strings.unload_confirmation_msg; window.event.returnValue = data.strings.unload_confirmation_msg; return data.strings.unload_confirmation_msg; } From 7449bf951d7977db014bac945f85df4225c3655f Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 16:27:13 -0400 Subject: [PATCH 48/63] Not actually used, comment it out. --- assets/js/admin/settings-views-html-settings-tax.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index e9c6da6df59..5d0bded8c53 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -62,7 +62,7 @@ initialize : function() { this.qty_pages = Math.ceil( this.model.get( 'rates' ).length / this.per_page ); this.listenTo( this.model, 'change', this.setUnloadConfirmation ); - this.listenTo( this.model, 'saved', this.clearUnloadConfirmation ); + // this.listenTo( this.model, 'saved', this.clearUnloadConfirmation ); $(window).on( 'beforeunload', { view : this }, this.unloadConfirmation ); }, setUnloadConfirmation : function() { From 97251f80b64cd8e88b10ffcc0b97fae3a6d1684c Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 16:51:06 -0400 Subject: [PATCH 49/63] Swap to associative array for model. --- assets/js/admin/settings-views-html-settings-tax.js | 5 +++-- includes/admin/settings/class-wc-settings-tax.php | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 5d0bded8c53..7b2d45b582f 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -17,7 +17,7 @@ per_page : data.limit, page : data.page, render : function() { - var rates = this.model.get( 'rates' ), + var rates = $.map( this.model.get( 'rates' ), function(v){return [v]} ), qty_rates = rates.length, qty_pages = Math.ceil( qty_rates / this.per_page ), first_index = this.per_page * ( this.page - 1), @@ -60,7 +60,8 @@ } }, initialize : function() { - this.qty_pages = Math.ceil( this.model.get( 'rates' ).length / this.per_page ); + this.per_page = 3; + this.qty_pages = Math.ceil( $.map( this.model.get( 'rates' ), function(v){return [v]} ).length / this.per_page ); this.listenTo( this.model, 'change', this.setUnloadConfirmation ); // this.listenTo( this.model, 'saved', this.clearUnloadConfirmation ); $(window).on( 'beforeunload', { view : this }, this.unloadConfirmation ); diff --git a/includes/admin/settings/class-wc-settings-tax.php b/includes/admin/settings/class-wc-settings-tax.php index 857558a1958..812caa340f7 100644 --- a/includes/admin/settings/class-wc-settings-tax.php +++ b/includes/admin/settings/class-wc-settings-tax.php @@ -149,7 +149,7 @@ class WC_Settings_Tax extends WC_Settings_Page { // Localize and enqueue our js. wp_localize_script( 'wc-settings-tax', 'htmlSettingsTaxLocalizeScript', array( 'current_class' => $current_class, - 'rates' => array_values( $rates ), + 'rates' => $rates, 'page' => ! empty( $_GET['p'] ) ? absint( $_GET['p'] ) : 1, 'limit' => 100, 'countries' => $countries, From 396752236c1a02142a931b4b348a114751003dce Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 16:51:26 -0400 Subject: [PATCH 50/63] Don't base size of news off the dom. --- assets/js/admin/settings-views-html-settings-tax.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 7b2d45b582f..11bf618a9e5 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -169,7 +169,7 @@ * Add a new blank row to the table for the user to fill out and save. */ $table.find('.insert').click(function() { - var size = $tbody.find('tr').length; + var size = Object.keys( WCTaxTableModelInstance.get( 'rates' ) ).length; var code = wp.template( 'wc-tax-table-row' )( { tax_rate_id : 'new-' + size, tax_rate_priority : 1, From dff70a05090903eae991ed7fc86e9e9c1e492f01 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 16:54:32 -0400 Subject: [PATCH 51/63] Add more data attributes to the rows and fields. --- .../settings/views/html-settings-tax.php | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index f035c637f99..0ccca044a77 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -46,7 +46,7 @@ if ( ! defined( 'ABSPATH' ) ) { From 5e8ef8f18d929c455548f21e88988143aee7866d Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 17:21:52 -0400 Subject: [PATCH 52/63] Check for truthiness. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids silliness where `’0’` evaluates to true. Just parse it as an int and evaluate that. --- includes/admin/settings/views/html-settings-tax.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index 0ccca044a77..caee89400e5 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -82,11 +82,11 @@ if ( ! defined( 'ABSPATH' ) ) { - checked="checked" <# } #> data-attribute="tax_rate_compound" /> + checked="checked" <# } #> data-attribute="tax_rate_compound" /> - checked="checked" <# } #> data-attribute="tax_rate_shipping" /> + checked="checked" <# } #> data-attribute="tax_rate_shipping" /> From ce02cd8a5b54d7d20cb4b5a7296d23b119e4b682 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 17:22:03 -0400 Subject: [PATCH 53/63] String.trim() polyfill. --- assets/js/admin/settings-views-html-settings-tax.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 11bf618a9e5..ad94955351b 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -6,6 +6,12 @@ (function($, data, wp){ $(function() { + if ( ! String.prototype.trim ) { + String.prototype.trim = function () { + return this.replace( /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '' ); + }; + } + var rowTemplate = wp.template( 'wc-tax-table-row' ), paginationTemplate = wp.template( 'wc-tax-table-pagination' ), $table = $( '.wc_tax_rates' ), From b80375ffbac8d5d3027d0e68635103e45816c4c5 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 17:24:06 -0400 Subject: [PATCH 54/63] Give the Model a setRateAttribute method. This should simplify updating when listening for changes in the form. --- assets/js/admin/settings-views-html-settings-tax.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index ad94955351b..6160f0807aa 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -17,7 +17,16 @@ $table = $( '.wc_tax_rates' ), $tbody = $( '#rates' ), $pagination = $( '#rates-pagination' ), - WCTaxTableModelConstructor = Backbone.Model.extend( {} ), + WCTaxTableModelConstructor = Backbone.Model.extend({ + setRateAttribute : function( rateID, attribute, value ) { + var rates = this.get( 'rates' ); + + if ( rates[ rateID ][ attribute ] !== value ) { + rates[ rateID ][ attribute ] = value; + this.set( 'rates', rates ); + } + } + } ), WCTaxTableViewConstructor = Backbone.View.extend({ rowTemplate : rowTemplate, per_page : data.limit, From 743dc23014739f95a81ffaf57ee45bcdae070454 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 17:24:37 -0400 Subject: [PATCH 55/63] Listen for changes in form inputs. When one is found, update the model to reflect the data in the dom. --- .../admin/settings-views-html-settings-tax.js | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 6160f0807aa..41e286a3181 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -80,6 +80,7 @@ this.listenTo( this.model, 'change', this.setUnloadConfirmation ); // this.listenTo( this.model, 'saved', this.clearUnloadConfirmation ); $(window).on( 'beforeunload', { view : this }, this.unloadConfirmation ); + $tbody.on( 'change', { view : this }, this.updateModelOnChange ); }, setUnloadConfirmation : function() { this.needsUnloadConfirm = true; @@ -94,6 +95,30 @@ return data.strings.unload_confirmation_msg; } }, + updateModelOnChange : function( event ) { + var model = event.data.view.model, + $target = $( event.target ), + id = $target.closest('tr').data('id'), + attribute = $target.data('attribute'), + val = $target.val(); + + if ( 'city' === attribute || 'postcode' === attribute ) { + val = val.split(';'); + val = $.map( val, function( thing ) { + return thing.trim(); + }); + } + + if ( 'tax_rate_compound' === attribute || 'tax_rate_shipping' === attribute ) { + if ( $target.is(':checked') ) { + val = 1; + } else { + val = 0; + } + } + + model.setRateAttribute( id, attribute, val ); + }, sanitizePage : function( page_num ) { page_num = parseInt( page_num, 10 ); if ( page_num < 1 ) { From fed3574434d93076273358eab5308e3202f33d76 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 17:29:52 -0400 Subject: [PATCH 56/63] Update the tablenav so the gotos are never out of range. --- includes/admin/settings/views/html-settings-tax.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index caee89400e5..cbfac9f3a04 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -101,7 +101,7 @@ if ( ! defined( 'ABSPATH' ) ) { - + @@ -113,7 +113,7 @@ if ( ! defined( 'ABSPATH' ) ) { '{{ data.qty_pages }}' ); ?> - + From 0afd9ebd6fcf607b6afa4d9a03a545100dc7be49 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 18:21:49 -0400 Subject: [PATCH 57/63] Be more specific as to what we're listening for. --- assets/js/admin/settings-views-html-settings-tax.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 41e286a3181..48fcdb2fdec 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -77,9 +77,9 @@ initialize : function() { this.per_page = 3; this.qty_pages = Math.ceil( $.map( this.model.get( 'rates' ), function(v){return [v]} ).length / this.per_page ); - this.listenTo( this.model, 'change', this.setUnloadConfirmation ); - // this.listenTo( this.model, 'saved', this.clearUnloadConfirmation ); $(window).on( 'beforeunload', { view : this }, this.unloadConfirmation ); + this.listenTo( this.model, 'change:rates', this.setUnloadConfirmation ); + // this.listenTo( this.model, 'saved:rates', this.clearUnloadConfirmation ); $tbody.on( 'change', { view : this }, this.updateModelOnChange ); }, setUnloadConfirmation : function() { From 992917caa046d6c85fd2f9b114508a960fa3621a Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 18:22:12 -0400 Subject: [PATCH 58/63] Manually trigger change event. Why? Unsure why this needs to be manually triggered, but its seems to. --- assets/js/admin/settings-views-html-settings-tax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 48fcdb2fdec..e331f6d53cf 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -24,6 +24,7 @@ if ( rates[ rateID ][ attribute ] !== value ) { rates[ rateID ][ attribute ] = value; this.set( 'rates', rates ); + this.trigger( 'change:rates' ); // Why is this necessary? Shouldn't the previous line trigger it? } } } ), From 50cf4e6fe58d2cc75f6a61c38499ea95bf393144 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 18:22:27 -0400 Subject: [PATCH 59/63] Reorder where we're running the before unload --- assets/js/admin/settings-views-html-settings-tax.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index e331f6d53cf..e2abb09eb65 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -78,10 +78,11 @@ initialize : function() { this.per_page = 3; this.qty_pages = Math.ceil( $.map( this.model.get( 'rates' ), function(v){return [v]} ).length / this.per_page ); - $(window).on( 'beforeunload', { view : this }, this.unloadConfirmation ); this.listenTo( this.model, 'change:rates', this.setUnloadConfirmation ); // this.listenTo( this.model, 'saved:rates', this.clearUnloadConfirmation ); $tbody.on( 'change', { view : this }, this.updateModelOnChange ); + + $(window).on( 'beforeunload', { view : this }, this.unloadConfirmation ); }, setUnloadConfirmation : function() { this.needsUnloadConfirm = true; From 64475025a6f59576bd16479c62106186d713d204 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 18:37:53 -0400 Subject: [PATCH 60/63] Kinda silly to have min length 3 on a field that holds max 2. --- assets/js/admin/settings-views-html-settings-tax.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index e2abb09eb65..0829ce5ae27 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -52,7 +52,7 @@ // Initialize autocomplete for countries. this.$el.find( 'td.country input' ).autocomplete({ source: data.countries, - minLength: 3 + minLength: 2 }); // Initialize autocomplete for states. From 4d8176a8053cf9ee8ca6b81462fb5f7b31511229 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 18:39:13 -0400 Subject: [PATCH 61/63] Remove debugging per_page override. --- assets/js/admin/settings-views-html-settings-tax.js | 1 - 1 file changed, 1 deletion(-) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index 0829ce5ae27..b00c873e8fd 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -76,7 +76,6 @@ } }, initialize : function() { - this.per_page = 3; this.qty_pages = Math.ceil( $.map( this.model.get( 'rates' ), function(v){return [v]} ).length / this.per_page ); this.listenTo( this.model, 'change:rates', this.setUnloadConfirmation ); // this.listenTo( this.model, 'saved:rates', this.clearUnloadConfirmation ); From 755b18bef2e2622f1251adc50f4f644d860fb1c9 Mon Sep 17 00:00:00 2001 From: George Stephanis Date: Mon, 10 Aug 2015 18:49:06 -0400 Subject: [PATCH 62/63] Add in a notification for unsaved changes. --- assets/js/admin/settings-views-html-settings-tax.js | 3 +++ includes/admin/settings/views/html-settings-tax.php | 2 ++ 2 files changed, 5 insertions(+) diff --git a/assets/js/admin/settings-views-html-settings-tax.js b/assets/js/admin/settings-views-html-settings-tax.js index b00c873e8fd..7e72129661b 100644 --- a/assets/js/admin/settings-views-html-settings-tax.js +++ b/assets/js/admin/settings-views-html-settings-tax.js @@ -16,6 +16,7 @@ paginationTemplate = wp.template( 'wc-tax-table-pagination' ), $table = $( '.wc_tax_rates' ), $tbody = $( '#rates' ), + $p_unsaved_msg = $( '#unsaved-changes' ), $pagination = $( '#rates-pagination' ), WCTaxTableModelConstructor = Backbone.Model.extend({ setRateAttribute : function( rateID, attribute, value ) { @@ -85,9 +86,11 @@ }, setUnloadConfirmation : function() { this.needsUnloadConfirm = true; + $p_unsaved_msg.show(); }, clearUnloadConfirmation : function() { this.needsUnloadConfirm = false; + $p_unsaved_msg.hide(); }, unloadConfirmation : function(event) { if ( event.data.view.needsUnloadConfirm ) { diff --git a/includes/admin/settings/views/html-settings-tax.php b/includes/admin/settings/views/html-settings-tax.php index cbfac9f3a04..b48d954318c 100644 --- a/includes/admin/settings/views/html-settings-tax.php +++ b/includes/admin/settings/views/html-settings-tax.php @@ -45,6 +45,8 @@ if ( ! defined( 'ABSPATH' ) ) { + +