0

I'm using the drupal/Geolocation module to assign a location field to a specific content-type.

I have created a View (REST Export display) to return all the content-type entries with all the fields and it's working fine.

I'd like to calculate the distance between a sent lat/lng point and the location of each entry and sort them by distance (and also include it in the resulting JSON).

I'm already applying some changes to the JSON output using the views_post_render hook (and changing the $output variable), but I don't think in that hook I can access a query string (sent via Ajax request).

What would be the best way to pass the user's location from the website frontend to the view? Right now my bet would be sending the query parameter via an Ajax request, adding something like ?location=-17.000,19.000 to the URL.

And where could I access that data (the user's lat/lng location) and calculate the distance to pass it again to the frontend?

0

I've found a solution.

Getting the user location

I'm using the Browser API to get the user location in the frontend and then pass those parameters as query strings to my view, like ?latitude=xxxx&longitude=xxxx.

if (navigator.geolocation) {
    var options = {
        enableHighAccuracy: true,
        maximumAge: 0
    };

    function success(pos) {
        var crd = pos.coords;
        // Send ajax request with crd.latitude and crd.longitude in query strings
    };

    function error(err) {
        console.warn(`ERROR(${err.code}): ${err.message}`);
    };

    navigator.geolocation.getCurrentPosition(success, error, options);
} else {
    console.warn('Geolocation not available.')
}

Using the location to calculate distances with Drupal hook

Then, using the THEME_views_post_render(\Drupal\views\ViewExecutable $view, &$output) hook I check that $view->id() is the view in which I want to make the calculations and I get the data from the URL using the Drupal function \Drupal::request()->query->get('latitude'); (and longitude).

From that point, I decode the JSON variable $output['#markup'] and change the JSON objects the way I need to fulfill my requirements.

if ($view->id() == 'farmacias_perto') {
        $user_latitude = \Drupal::request()->query->get('latitude');
        $user_longitude = \Drupal::request()->query->get('longitude');
        $json_result = json_decode($output['#markup']->jsonSerialize());

        foreach ($json_result as $pharmacy) {
            $latlong = explode(',', $pharmacy->field_geolocation);
            $pharmacy_latitude = $latlong[0];
            $pharmacy_longitude = $latlong[1];
            $distance = distance($pharmacy_latitude, $pharmacy_longitude, $user_latitude, $user_longitude);
            $pharmacy->distance = round($distance);
        }

        $output['#markup'] = json_encode($json_result);
}

I used the distance function explained here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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