2015-08-07 16:10:01 +00:00
|
|
|
/* global htmlSettingsTaxLocalizeScript */
|
2015-08-07 15:04:55 +00:00
|
|
|
/**
|
|
|
|
* Used by woocommerce/includes/admin/settings/views/html-settings-tax.php
|
|
|
|
*/
|
|
|
|
|
|
|
|
(function($, data, wp){
|
|
|
|
$(function() {
|
2015-08-07 19:36:12 +00:00
|
|
|
|
2015-08-10 21:22:03 +00:00
|
|
|
if ( ! String.prototype.trim ) {
|
|
|
|
String.prototype.trim = function () {
|
|
|
|
return this.replace( /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '' );
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2015-08-08 14:57:22 +00:00
|
|
|
var rowTemplate = wp.template( 'wc-tax-table-row' ),
|
2015-08-07 20:36:50 +00:00
|
|
|
paginationTemplate = wp.template( 'wc-tax-table-pagination' ),
|
2015-08-08 18:45:37 +00:00
|
|
|
$table = $( '.wc_tax_rates' ),
|
2015-08-08 14:57:22 +00:00
|
|
|
$tbody = $( '#rates' ),
|
2015-08-10 22:49:06 +00:00
|
|
|
$p_unsaved_msg = $( '#unsaved-changes' ),
|
2015-08-08 18:46:21 +00:00
|
|
|
$pagination = $( '#rates-pagination' ),
|
2015-08-12 18:30:26 +00:00
|
|
|
$search_field = $( '#rates-search .wc-tax-rates-search-field' ),
|
2015-08-10 21:24:06 +00:00
|
|
|
WCTaxTableModelConstructor = Backbone.Model.extend({
|
2015-08-10 22:54:25 +00:00
|
|
|
changes : {},
|
2015-08-10 21:24:06 +00:00
|
|
|
setRateAttribute : function( rateID, attribute, value ) {
|
|
|
|
var rates = this.get( 'rates' );
|
|
|
|
|
|
|
|
if ( rates[ rateID ][ attribute ] !== value ) {
|
|
|
|
rates[ rateID ][ attribute ] = value;
|
|
|
|
this.set( 'rates', rates );
|
2015-08-10 22:22:12 +00:00
|
|
|
this.trigger( 'change:rates' ); // Why is this necessary? Shouldn't the previous line trigger it?
|
2015-08-10 22:54:25 +00:00
|
|
|
|
|
|
|
// Store it in a changes array to potentially simplify saving?
|
|
|
|
this.changes[ rateID ] = this.changes[ rateID ] || {};
|
|
|
|
this.changes[ rateID ][ attribute ] = value;
|
2015-08-10 21:24:06 +00:00
|
|
|
}
|
2015-08-12 18:31:07 +00:00
|
|
|
},
|
|
|
|
getFilteredRates : function() {
|
|
|
|
var rates = this.get( 'rates' ),
|
|
|
|
search = $search_field.val().toLowerCase();
|
|
|
|
|
|
|
|
if ( search.length ) {
|
|
|
|
rates = _.filter( rates, function( rate ) {
|
2015-08-12 18:41:52 +00:00
|
|
|
var search_text = _.toArray( rate ).join( ' ' ).toLowerCase();
|
2015-08-12 18:31:07 +00:00
|
|
|
return ( -1 !== search_text.indexOf( search ) );
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
|
|
|
return rates;
|
2015-08-10 21:24:06 +00:00
|
|
|
}
|
|
|
|
} ),
|
2015-08-08 18:46:21 +00:00
|
|
|
WCTaxTableViewConstructor = Backbone.View.extend({
|
|
|
|
rowTemplate : rowTemplate,
|
|
|
|
per_page : data.limit,
|
|
|
|
page : data.page,
|
|
|
|
render : function() {
|
2015-08-12 18:43:48 +00:00
|
|
|
var rates = this.model.getFilteredRates(),
|
2015-08-08 18:46:21 +00:00
|
|
|
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,
|
2015-08-12 18:43:48 +00:00
|
|
|
paged_rates = _.toArray( rates ).slice( first_index, last_index ),
|
2015-08-08 18:46:21 +00:00
|
|
|
view = this;
|
|
|
|
|
|
|
|
// Blank out the contents.
|
|
|
|
this.$el.empty();
|
|
|
|
|
|
|
|
// Populate $tbody with the current page of results.
|
|
|
|
$.each( paged_rates, function ( id, rowData ) {
|
|
|
|
view.$el.append( view.rowTemplate( rowData ) );
|
|
|
|
});
|
|
|
|
|
|
|
|
// Initialize autocomplete for countries.
|
|
|
|
this.$el.find( 'td.country input' ).autocomplete({
|
|
|
|
source: data.countries,
|
2015-08-10 22:37:53 +00:00
|
|
|
minLength: 2
|
2015-08-08 18:46:21 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
this.$el.find( 'td.postcode input, td.city input' ).change(function() {
|
|
|
|
$(this).attr( 'name', $(this).data( 'name' ) );
|
|
|
|
});
|
|
|
|
|
|
|
|
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
|
|
|
|
} ) );
|
|
|
|
}
|
|
|
|
},
|
2015-08-12 18:19:45 +00:00
|
|
|
updateUrl : function() {
|
|
|
|
if ( ! window.history.replaceState ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var url = data.base_url,
|
|
|
|
search = $search_field.val();
|
|
|
|
|
|
|
|
if ( 1 < this.page ) {
|
|
|
|
url += '&p=' + encodeURIComponent( this.page );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( search.length ) {
|
|
|
|
url += '&s=' + encodeURIComponent( search );
|
|
|
|
}
|
|
|
|
|
|
|
|
window.history.replaceState( {}, '', url );
|
|
|
|
},
|
2015-08-08 18:46:21 +00:00
|
|
|
initialize : function() {
|
2015-08-12 18:39:34 +00:00
|
|
|
this.qty_pages = Math.ceil( _.toArray( this.model.get( 'rates' ) ).length / this.per_page );
|
2015-08-12 18:17:50 +00:00
|
|
|
this.page = this.sanitizePage( data.page );
|
|
|
|
|
2015-08-10 22:21:49 +00:00
|
|
|
this.listenTo( this.model, 'change:rates', this.setUnloadConfirmation );
|
|
|
|
// this.listenTo( this.model, 'saved:rates', this.clearUnloadConfirmation );
|
2015-08-10 21:24:37 +00:00
|
|
|
$tbody.on( 'change', { view : this }, this.updateModelOnChange );
|
2015-08-12 19:01:27 +00:00
|
|
|
$search_field.on( 'keyup search', { view : this }, this.onSearchField );
|
|
|
|
$pagination.on( 'click', 'a', { view : this }, this.onPageChange );
|
|
|
|
$pagination.on( 'change', 'input', { view : this }, this.onPageChange );
|
2015-08-10 22:22:27 +00:00
|
|
|
$(window).on( 'beforeunload', { view : this }, this.unloadConfirmation );
|
2015-08-10 14:29:11 +00:00
|
|
|
},
|
2015-08-12 19:01:27 +00:00
|
|
|
onSearchField : function( event ){
|
|
|
|
event.data.view.updateUrl();
|
|
|
|
event.data.view.render();
|
|
|
|
},
|
|
|
|
onPageChange : function( event ) {
|
|
|
|
var $target = $( event.currentTarget );
|
|
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
view.page = $target.data('goto') ? $target.data('goto') : $target.val();
|
|
|
|
view.render();
|
|
|
|
view.updateUrl();
|
|
|
|
},
|
2015-08-10 14:29:11 +00:00
|
|
|
setUnloadConfirmation : function() {
|
|
|
|
this.needsUnloadConfirm = true;
|
2015-08-10 22:49:06 +00:00
|
|
|
$p_unsaved_msg.show();
|
2015-08-10 14:29:11 +00:00
|
|
|
},
|
|
|
|
clearUnloadConfirmation : function() {
|
|
|
|
this.needsUnloadConfirm = false;
|
2015-08-10 22:49:06 +00:00
|
|
|
$p_unsaved_msg.hide();
|
2015-08-10 14:29:11 +00:00
|
|
|
},
|
2015-08-10 20:27:04 +00:00
|
|
|
unloadConfirmation : function(event) {
|
|
|
|
if ( event.data.view.needsUnloadConfirm ) {
|
|
|
|
event.returnValue = data.strings.unload_confirmation_msg;
|
2015-08-10 14:29:11 +00:00
|
|
|
window.event.returnValue = data.strings.unload_confirmation_msg;
|
|
|
|
return data.strings.unload_confirmation_msg;
|
|
|
|
}
|
2015-08-08 18:46:21 +00:00
|
|
|
},
|
2015-08-10 21:24:37 +00:00
|
|
|
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 );
|
|
|
|
},
|
2015-08-08 18:46:21 +00:00
|
|
|
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({
|
2015-08-10 20:02:32 +00:00
|
|
|
rates : data.rates
|
2015-08-08 18:46:21 +00:00
|
|
|
} ),
|
|
|
|
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'
|
|
|
|
} );
|
2015-08-07 15:42:49 +00:00
|
|
|
|
2015-08-08 18:46:37 +00:00
|
|
|
WCTaxTableInstance.render();
|
2015-08-07 20:58:42 +00:00
|
|
|
|
2015-08-07 19:36:12 +00:00
|
|
|
/**
|
2015-08-08 14:57:03 +00:00
|
|
|
* Handle the exporting of tax rates, and build it off the global `data.rates` object.
|
2015-08-07 19:36:12 +00:00
|
|
|
*
|
2015-08-08 14:57:03 +00:00
|
|
|
* @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.
|
2015-08-07 19:36:12 +00:00
|
|
|
*/
|
2015-08-08 14:57:46 +00:00
|
|
|
$table.find('.export').click(function() {
|
2015-08-07 19:36:12 +00:00
|
|
|
var csv_data = 'data:application/csv;charset=utf-8,' + data.strings.csv_data_cols.join(',') + '\n';
|
|
|
|
|
2015-08-08 14:57:03 +00:00
|
|
|
$.each( data.rates, function( id, rowData ) {
|
2015-08-07 19:36:12 +00:00
|
|
|
var row = '';
|
2015-08-08 14:57:03 +00:00
|
|
|
|
|
|
|
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';
|
2015-08-07 15:42:49 +00:00
|
|
|
});
|
|
|
|
|
2015-08-07 19:36:12 +00:00
|
|
|
$(this).attr( 'href', encodeURI( csv_data ) );
|
2015-08-07 15:42:49 +00:00
|
|
|
|
2015-08-07 19:36:12 +00:00
|
|
|
return true;
|
|
|
|
});
|
2015-08-07 15:42:49 +00:00
|
|
|
|
2015-08-07 19:36:12 +00:00
|
|
|
/**
|
|
|
|
* Add a new blank row to the table for the user to fill out and save.
|
|
|
|
*/
|
2015-08-08 14:57:46 +00:00
|
|
|
$table.find('.insert').click(function() {
|
2015-08-10 20:51:26 +00:00
|
|
|
var size = Object.keys( WCTaxTableModelInstance.get( 'rates' ) ).length;
|
2015-08-07 19:36:12 +00:00
|
|
|
var code = wp.template( 'wc-tax-table-row' )( {
|
|
|
|
tax_rate_id : 'new-' + size,
|
|
|
|
tax_rate_priority : 1,
|
|
|
|
tax_rate_shipping : 1,
|
|
|
|
newRow : true
|
|
|
|
} );
|
|
|
|
|
|
|
|
if ( $tbody.find('tr.current').length > 0 ) {
|
|
|
|
$tbody.find('tr.current').after( code );
|
|
|
|
} else {
|
|
|
|
$tbody.append( code );
|
|
|
|
}
|
|
|
|
|
|
|
|
$( 'td.country input' ).autocomplete({
|
|
|
|
source: data.countries,
|
|
|
|
minLength: 3
|
|
|
|
});
|
2015-08-07 15:42:49 +00:00
|
|
|
|
2015-08-07 19:36:12 +00:00
|
|
|
$( 'td.state input' ).autocomplete({
|
|
|
|
source: data.states,
|
|
|
|
minLength: 3
|
|
|
|
});
|
2015-08-07 15:42:49 +00:00
|
|
|
|
2015-08-07 19:36:12 +00:00
|
|
|
return false;
|
2015-08-07 15:42:49 +00:00
|
|
|
});
|
|
|
|
|
2015-08-12 18:44:24 +00:00
|
|
|
/**
|
|
|
|
* Removals.
|
|
|
|
*/
|
|
|
|
$table.find('.remove_tax_rates').click(function() {
|
|
|
|
if ( $tbody.find('tr.current').length > 0 ) {
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
window.alert( data.strings.no_rows_selected );
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
2015-08-07 15:42:49 +00:00
|
|
|
});
|
2015-08-07 15:04:55 +00:00
|
|
|
})(jQuery, htmlSettingsTaxLocalizeScript, wp);
|