So I've modified a piece of code that includes a call to the Google Distance Matrix API.

I wanted it to only work out the distance to a specific address. But I now also want to use it on a different page than originally intended.

I've created a second shortcode, which creates a second form with a different postcode in the hidden field, but while the first form works fine, the second one doesn't do anything.

Can anyone help?

Code below with addresses and API keys removed

<?php
/**
 * Plugin Name: WP Distance Calculator
 * Plugin URI: http://phpcodingschool.blogspot.com/
 * Description: This plugin claculates distance between two near by locations.
 * Version: 1.0.0
 * Author: Monika Yadav
 * Author URI: http://phpcodingschool.blogspot.com/
 * License: GPL2
 */

class DistanceWPCalculator
{
    public function __construct()
    {       //action definations
            add_shortcode( 'distance_calculator',  array( &$this, 'distanceWPfrontend' ) ); 
            add_shortcode( 'distance_calculator_LC',  array( &$this, 'distanceWPfrontendLC' ) ); 
            add_action( 'wp_ajax_nopriv_distancewpcalculator', array( &$this, 'distancewpcalculator_calculate' ) );
            add_action( 'wp_ajax_distancewpcalculator', array( &$this, 'distancewpcalculator_calculate' ) );


            add_action( 'init', array( &$this, 'init' ) );

    }

    public function init()
    {
        wp_enqueue_script( 'distancewpcalculator', plugin_dir_url( __FILE__ ) . 'js/calculatedistance.js', array( 'jquery' ) );
        wp_localize_script( 'distancewpcalculator', 'DistanceCalculator', array(
            'ajaxurl' => admin_url( 'admin-ajax.php' )
        ) );
        ?>
        <script>
        var ajaxurl =  "<?php echo admin_url('admin-ajax.php'); ?>";
        </script>
        <?php
        wp_enqueue_style( 'DistanceWPCalculator-Style', plugin_dir_url( __FILE__ ) . 'css/style.css', array(), '0.1', 'screen' );
    }



    public function distancewpcalculator_calculate()
    {   
        // The $_POST contains all the data sent via ajax
        if ( isset($_POST) ) {

        $from = urlencode($_POST['from']);
        $to = urlencode($_POST['to']);
        $data = file_get_contents("https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=$from&destinations=$to&key=");
        $data = json_decode($data);
        $time = 0;
        $distance = 0;
            foreach($data->rows[0]->elements as $road) {
                $time += $road->duration->value;
                $distance += $road->distance->value;
            }
            $time =$time/60;
            $distance =round($distance/1000);
            //Output
            if($distance!=0){

            echo "<div id='result_generated'>";
            echo "From: ".$data->origin_addresses[0];
            echo "<br/>";
            echo "To:".$data->destination_addresses[0];
            echo "<br/>";
            echo "Time: ".gmdate("H:i", ($time * 60))." hour(s)";
            echo "<br/>";
            echo "Distance: ".$distance." miles";
            echo "</div>";         
            }else{
            echo "Sorry only nearby distance can be calculated."; 
            }                
           }

    die();

    }


    //Function to display form on front-end
    public function distanceWPfrontend( $atts ) {

    ?>  
        <form method = "post" id="calculator" >
            <div class="DC_title">Distance Calculator</div>
            <input type="hidden" id="to" name="to" value="Postcode 1">
            <input type="text" id="from" name="from" placeholder="From.."></br>
            <input type="button" id="calculate" name="calculate" value="Calculate" class="wpcf7-form-control wpcf7-submit btn btn-accent btn-lg">
        </form></br>
        <div id="result"></div> 
        <?php
    }

    public function distanceWPfrontendLC( $atts ) {

    ?>  
        <form method = "post" id="calculator" >
            <div class="DC_title">Distance Calculator</div>
            <input type="hidden" id="to" name="to" value="Postcode2">
            <input type="text" id="from" name="from" placeholder="From.."></br>
            <input type="button" id="calculate" name="calculate" value="CalculateLC" class="wpcf7-form-control wpcf7-submit btn btn-accent btn-lg">
        </form></br>
        <div id="result"></div> 
        <?php
    }


    }

    $distancewpcalculator = new DistanceWPCalculator();

?>

JS

jQuery( document ).ready(function() {

jQuery("#calculate").click( function(){ 
    // This does the ajax request
     var from = jQuery('#from').val();
     var to = jQuery('#to').val();

jQuery.ajax({

    url : ajaxurl,
    type : 'POST',
    data: {
        'action':'distancewpcalculator',
        'from' : from,
        'to' : to            
    },
    success:function(data) {
        // This outputs the result of the ajax request
        jQuery('#result').html(data);
    },
    error: function(errorThrown){
        console.log(errorThrown);
    }
});
});

});

  • Your results are returned based on an AJAX request by your JavaScript, so you'd need to check your JavaScript for issues. – Jacob Peattie Dec 7 at 10:57
  • @JacobPeattie it works fine in the short code Distance_Calculator though, but the Distance_calculator_LC short code doesn't do anything, the only difference being the hardcoded "to" Even if I leave it the same, the second one doesn't work. So I must have done something wrong in my declartion of the second shortcode or the form? – Andy Smith-Dane Dec 7 at 11:02
  • The behaviour of submitting the form in the shortcode is entirely handled by your JavaScript. So no, it is not the shortcode that has to be the problem. Please at least include it in the question. – Jacob Peattie Dec 7 at 11:06
  • @JacobPeattie got you, added the JS in the original Question, thanks. – Andy Smith-Dane Dec 7 at 11:11
  • Are both these shortcodes being used on the same page? – Jacob Peattie Dec 7 at 11:13
up vote 0 down vote accepted

The problem is that if your JavaScript is referring to the IDs of the forms and inputs, so if you have both on the same page the script will only run with the values of the first form.

The simplest solution would be to use different IDs for the elements in each shortcode, but a better permanent solution would be to make you script work based on a class, and use the values from the submitted form, rather than global IDs.

So change your form to just have a class on the form element:

<form class="distance-calculator">
    <input type="hidden" name="to" value="Postcode2">
    <input type="text" name="from">
    <input type="submit" value="Calculate">
</form>
<div class="result"></div> 

I've removed everything not relevant to the question for clarity. I also removed method="post" since POST is not appropriate for getting a value. I also changed the result div to use a class.

Then update your JavaScript to target submission of the .distance-calculator form, and use the from and to value only from the submitted form. Then use only the .result after the form.

jQuery( '.distance-calculator' ).on( 'submit', function( event ) {
    event.preventDefault();

    var form = this;

    var from = form.from.value;
    var to   = form.to.value;

    jQuery.ajax( {
        url : ajaxurl,
        type : 'GET',
        data: {
            'action' : 'distancewpcalculator',
            'from' : from,
            'to' : to
        },
        success: function( data ) {
            jQuery.next( '.result' ).html( data );
        },
        error: function( errorThrown ) {
            console.log(errorThrown);
        }
    } );
} );

I also changed the POST to GET here. As I mentioned before POST is not appropriate for this type of request. POST should only be used for creating or updating a resource, while GET should be used for retrieving data. It just means you'll need to update your PHP to use $_GET instead of $_POST.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.