products

Advanced JavaScript Functions for WooCommerce Table Rate Shipping Plugin

To make the table rate plugin a little more useful

This plugin is for importing & exporting price tables from the WooCommerce Table Rate Shipping plugin. A feature request had been submitted, but it was never resolved, so I created my own.
Advanced JavaScript Functions for WooCommerce Table Rate Shipping PluginWoocommerce Table Rate Shipping import/export function – WooCommerceI’d love to see an import/export function in “Woocommerce Table Rate Shipping”. It is very useful for developers. Sometimes, we have to fill hundreds of shipping prices. With an export/import function, i could easily copy my configuration from a site to another one. WooCommerce

It adds buttons under a price table within each Shipping Method to allow exporting or importing of its table. Want to import/export all shipping data at once? Unfortunately, I do not provide it. Instead, try the well-known rynaldo plugin: http://rynaldo.com/how-to-import-and-export-your-woocommerce-shipping-zones-methods-and-rates-from-one-site-to-another/

In my operational case, it was more convenient, safer, and easier to change tables one by one, because I could create them using only JavaScript. For example, you can manage your fee tables in Excel and import them into WooCommerce.

If you like, you can read the code below or download the zip file and try it out. However, this is a simple plugin and the testing environment is limited, I cannot guarantee that it will work as you expected. Please use at your own risk.

Download as Zip (v1.1 30.Mar.2023)

Import and Export Table Rate in CSV

There is no configuration just to install. To operate, simply press the Import or Export button.

Advanced JavaScript Functions for WooCommerce Table Rate Shipping Plugin

Note: CSV must be implemented in UTF8. Do not include commas in the numbers.

Copy and Paste Shipping Zones

One more thing, you can copy and paste shipping zones implemented in select2. Click “Copy Zones” link to copy a sequence to a clipboard and paste it into other zones. A copied array is saved to a clipboard as follows, separated by commas

state:CA:AB,state:CA:BC,state:CA:MB,country:MX,country:US

In other words, if you follow this writing style, you can paste your own arrays. This feature is also available in the general tab of wc-settings.
Advanced JavaScript Functions for WooCommerce Table Rate Shipping Plugin

Codes included in the plugin

These php codes only specify the loading of JavaScript. So, instead of installing them as plug-ins, it would be possible to place JavaScript files anywhere and instruct them to be loaded from functions.php.

add_action( 'admin_enqueue_scripts', function () {
  wp_register_script( 'woocommerce_table_rate_shipping_advanced_js', plugins_url( '/table-rate-advanced.js', __FILE__ ), array( 'jquery', 'wp-util' ), '', true );
});

add_action( 'woocommerce_after_settings_shipping', function ( ) { // Import / Export Table rates.
  wp_enqueue_script( 'woocommerce_table_rate_shipping_advanced_js' );
});

add_action('woocommerce_after_settings_general', function () {
  wp_enqueue_script( 'woocommerce_table_rate_shipping_advanced_js' );
});

Here is the Jquery code.

Note: When importing a price list using this plugin, existing table rows are deleted from the database via Ajax. This is undesirable behavior, especially if the imported data is inaccurate. This is due to the specification that the original Table Rate plugin does not delete old ones from the database when saving a price list. To work around this problem, I need to make more modifications to this plugin.

( function( $, wp, ajaxurl ) {
  $('#zone_locations, [name^="woocommerce_all_except_countries"], [name^="woocommerce_specific_allowed_countries"], [name^="woocommerce_specific_ship_to_countries"]').each( function(){
    let zone_select = $(this);
    let zone_copy = $('<a href="#" class="copy" style="display:block; font-weight:normal; margin:8px 0 0;">Copy Zones</a>');
    console.log( $(this).attr('name') );
    $(this).parent('td').prev('th').append( zone_copy );
    zone_copy.on('click', function(){
      alert("Shipping Zones were copied. Paste on others.");
      navigator.clipboard.writeText( zone_select.val() ); // Available only under https environment
    });
    zone_select.parent().on('paste', function (e) {
      var locations = $.merge( zone_select.val(), (e.originalEvent || e).clipboardData.getData('text/plain').split(/[\,\s]+/));
      if ( locations && Array.isArray(locations) ){
        e.preventDefault();
        zone_select.val(locations).trigger('change');
      }
    });
  });

  let wc_table_rate_rows_row_template = wp.template( 'table-rate-shipping-row-template' ),
    wc_table_rate_tbody = $( '#shipping_rates' ).find( 'tbody.table_rates' ),
    wc_table_rate_button = $( '<label for="woocommerce_table_rate_import_rates" class="button">Import</label>' ),
    wc_table_rate_import = $( '<input id="woocommerce_table_rate_import_rates" style="display:none;" type="file">' ),
    wc_table_rate_export = $( '<button style="margin-left:8px;"id="woocommerce_table_rate_export_rates_button" class="button" type="button" value="">Export</button>' ),
    wc_table_rate_message = $( '<span id="woocommerce_table_rate_import_message" style="padding:0 8px; line-height:2; color:red;"></span>' ),
    wc_table_rate_reader = new FileReader();
  $( '<div id="woocommerce_table_rate_import_rates_wrapper" style="padding:16px 0; text-align:right"></div>' ).insertAfter( '#shipping_rates' ).append( wc_table_rate_message ).append( wc_table_rate_button ).append( wc_table_rate_import ).append( wc_table_rate_export );

  wc_table_rate_export.on( 'click', function(event){
    let csv_list = '', csv_header = '';
    event.preventDefault();
    wc_table_rate_tbody.find( 'tr' ).each( function( ignore, elem ) {
      $(elem).find("input:not(.rate_id):not([name=select]), select").each(function (i, col) {
        if ( ignore == 0 ) {
          if (i != 0 ) {
            csv_header += ',';
          }
          csv_header += $(col).attr('name').replace('[0]','');
        }
        if (i == 0 ) {
          csv_list += '\r\n';
        } else {
          csv_list += ',';
        }
        if ( $(col).attr('type') == 'checkbox' ){
          if ( $(col).is(':checked') ){
            csv_list += '1';
          }
        } else {
          csv_list += '"' + $(col).val() + '"';
        }
      });
    });
    let wc_table_rate_blob =new Blob([csv_header+csv_list],{type:"text/csv"}); // Set the above string in the array
    let wc_table_rate_link = document.createElement('a');
    wc_table_rate_link.href = URL.createObjectURL(wc_table_rate_blob);
    const urlParams = new URLSearchParams(window.location.search);
    const file_dt = new Date();
    wc_table_rate_link.download = "table_rate_"+urlParams.get('instance_id')+"-"+file_dt.getFullYear() + ("00" + (file_dt.getMonth()+1)).slice(-2) + ("00" + (file_dt.getDate())).slice(-2)+".csv";
    wc_table_rate_link.click();
  });

  function split_csv_to_array(row) {
    let re_valid = /^\s*(?:'[^'\\]*(?:\\[\S\s][^'\\]*)*'|"[^"\\]*(?:\\[\S\s][^"\\]*)*"|[^,'"\s\\]*(?:\s+[^,'"\s\\]+)*)\s*(?:,\s*(?:'[^'\\]*(?:\\[\S\s][^'\\]*)*'|"[^"\\]*(?:\\[\S\s][^"\\]*)*"|[^,'"\s\\]*(?:\s+[^,'"\s\\]+)*)\s*)*$/;
    let re_value = /(?!\s*$)\s*(?:'([^'\\]*(?:\\[\S\s][^'\\]*)*)'|"([^"\\]*(?:\\[\S\s][^"\\]*)*)"|([^,'"\s\\]*(?:\s+[^,'"\s\\]+)*))\s*(?:,|$)/g;
    if (!re_valid.test(row)) return null; // If string is not CSV
    let result = [];
    row.replace(re_value,
      function(m0, m1, m2, m3) {
        if      (m1 !== undefined) result.push(m1.replace(/\\'/g, "'")); // Remove backslash
        else if (m2 !== undefined) result.push(m2.replace(/\\"/g, '"')); // Remove backslash
        else if (m3 !== undefined) result.push(m3);
        return '';
      });
    if (/,\s*$/.test(row)) result.push('');
    return result;
  };

  wc_table_rate_import.on( 'change', function(){
    if ( wc_table_rate_tbody.find( 'tr.table_rate' ).length && confirm( 'Delete the existing rows?' ) ) {
      var rate_ids  = [];
      wc_table_rate_tbody.find( 'tr input.rate_id' ).each( function( i, el ) {
        rate_ids.push( $(el).val() );
      });
      var ajax_data = {
        action: 'woocommerce_table_rate_delete',
        rate_id: rate_ids,
        security: (typeof woocommerce_shipping_table_rate_rows !== 'undefined') ? woocommerce_shipping_table_rate_rows.delete_rates_nonce : ''
      };
      $.post( ajaxurl, ajax_data, function(response) {
        wc_table_rate_tbody.find( 'tr.table_rate' ).remove();
        wc_table_rate_reader.readAsText(wc_table_rate_import.prop("files")[0], "UTF-8");
      });
    } else {
      wc_table_rate_reader.readAsText(wc_table_rate_import.prop("files")[0], "UTF-8");
    }
  });
  let csv_items = [];
  wc_table_rate_reader.onload = () => {
    let wc_table_rate_result = wc_table_rate_reader.result.split(/\r\n|\n/);
    let csv_header;
    if ( wc_table_rate_result[0].indexOf('"') === 0 && row.lastIndexOf('"') === wc_table_rate_result[0].length - 1 ) {
      csv_header = wc_table_rate_result[0].substring(1, wc_table_rate_result[0].length - 1).split('","');
    } else {
      csv_header = wc_table_rate_result[0].split(',');
    }
    wc_table_rate_result.shift(); // SKip first row
    csv_items = wc_table_rate_result.map(row => {
      let result = {};
      let datas = split_csv_to_array(row);
      for (const index in datas) {
        let key = csv_header[index];
        result[key] = datas[index];
      }
      return result;
    });
    for (item of csv_items) {
      var size   = wc_table_rate_tbody.find( '.table_rate' ).length;
      wc_table_rate_tbody.append( wc_table_rate_rows_row_template( {
        rate:  {
          rate_id: item.index,
          rate_class: item.shipping_class,
          rate_condition: item.shipping_condition,
          rate_min: item.shipping_min,
          rate_max: item.shipping_max,
          rate_priority: item.shipping_priority,
          rate_abort: item.shipping_abort,
          rate_abort_reason: item.shipping_abort_reason,
          rate_cost: item.shipping_cost,
          rate_cost_per_item: item.shipping_per_item,
          rate_cost_per_weight_unit: item.shipping_cost_per_weight,
          rate_cost_percent: item.shipping_cost_percent,
          rate_label: item.shipping_label
        },
        index: size
      } ) );

    }
    $( '#woocommerce_table_rate_calculation_type, #shipping_rates select[name^="shipping_condition"], #shipping_rates input[name^="shipping_abort"]' ).change();
    wc_table_rate_message.html("Imported " + csv_items.length + " rows. Confirm and Save changes.");
  }
  // when a file failed
  wc_table_rate_reader.onerror = () => {
    csv_items = [];
    wc_table_rate_message.html("Import failed.");
  }
})( jQuery, wp, ajaxurl );

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です