question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

how to automatically find map addres as customer write in fields - using jquery

See original GitHub issue

Hi and thank you all for this great package 😃 I am trying to make my signup form more user friendly and i would like user first to write his address etc, and then (i hope) that this widget can find address automaticlly for most users. This is what I have done so far… some jquery that insert the address in the widget autocomplete address field. But it doesnt work the magic. I need the last little bit, please help me 😃

  <script type="text/javascript">
    $( document ).ready(function() {
      $(document).on("click", "#id_street, #id_zipcode, #id_city, #id_country", function(event){
        if ($("#id_street").val() && $("#id_zipcode").val() && $("#id_city").val() && $("#id_country").val()){
          $("#location-mw-google-address-input").val($("#id_street").val() + ", " + $("#id_zipcode").val() + " " + $("#id_city").val() + ", " + $("#id_country option:selected").text())
        }
      });
    });
  </script>

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:12 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
eriktelepovskycommented, Mar 29, 2018

Hi @michaelhjulskov I have a working solution 😉

To add or delete a marker, you need access to DjangoGooglePointFieldWidget instance in your JavaScript. I opened an issue for that #62 I believe author will agree with me or he will give me better approach how to use it.

Next thing you need to do is to override template file which renders the map. In my case it was google-point-field-widget.html. So go ahead and create a file with the same name in your app in the path templates/mapwidgets/

You can either paste the whole content there or just extend it like I do:

{% extends "mapwidgets/google-point-field-widget.html" %}

{% load i18n %}

{% block javascript %}
    <script type="application/javascript">
        (function($) {
            var mapOptions = JSON.parse("{{ options|escapejs }}");
            var field_value = JSON.parse("{{ field_value|escapejs }}");

            var wrapElemSelector = "#{{ name }}-mw-wrap";
            var mapElemID = "{{ name }}-map-elem";
            var googleAutoInputID = "{{ name }}-mw-google-address-input";
            var locationInputID = "#{{ id }}";

            var mapWidgetOptions = {
                locationInput: $(locationInputID),
                wrapElemSelector: wrapElemSelector,
                locationFieldValue: field_value,
                mapElement: document.getElementById(mapElemID),
                mapCenterLocationName: mapOptions.mapCenterLocationName,
                mapCenterLocation: mapOptions.mapCenterLocation,
                coordinatesOverlayToggleBtn: $(".mw-btn-coordinates", wrapElemSelector),
                coordinatesOverlayDoneBtn: $(".mw-btn-coordinates-done", wrapElemSelector),
                coordinatesOverlayInputs: $(".mw-overlay-input", wrapElemSelector),
                coordinatesOverlay: $(".mw-coordinates-overlay", wrapElemSelector),
                myLocationBtn: $(".mw-btn-my-location", wrapElemSelector),
                addressAutoCompleteInput: document.getElementById(googleAutoInputID),
                deleteBtn: $(".mw-btn-delete", wrapElemSelector),
                addMarkerBtn: $(".mw-btn-add-marker", wrapElemSelector),
                loaderOverlayElem: $(".mw-loader-overlay", wrapElemSelector),
                zoom: mapOptions.zoom,
                markerFitZoom: mapOptions.markerFitZoom,
                GooglePlaceAutocompleteOptions: mapOptions.GooglePlaceAutocompleteOptions,
                markerCreateTriggerNameSpace: "google_point_map_widget:marker_create",
                markerChangeTriggerNameSpace: "google_point_map_widget:marker_change",
                markerDeleteTriggerNameSpace: "google_point_map_widget:marker_delete",
                placeChangedTriggerNameSpace: "google_point_map_widget:place_changed"
            };
            var widget = new DjangoGooglePointFieldWidget(mapWidgetOptions);
            map_widget_autofill(widget);

            {% block extra_javascript %}

            {% endblock %}
        })(jQuery || django.jQuery);
    </script>
{% endblock javascript %}

Please notice these 2 changed lines:

var widget = new DjangoGooglePointFieldWidget(mapWidgetOptions);
map_widget_autofill(widget);

I haven’t touched anything else in this file.

map_widget_autofill() is my own function I have in my JavaScript file script.js. I will describe it below.

You need to tell Django to load your static file in the admin.py:

class MyModelAdminForm(forms.ModelForm):
    class Meta:
        model = MyModel
        exclude = []
        widgets = {
            'point': GooglePointFieldWidget
        }

@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
    form = MyModelAdminForm
    ...

    class Media:
        js = (
            'js/script.js',
        )

And finally script.js:

(function($) {
    map_widget_autofill = function (widget) {
        var locationInput = widget.locationInput;
        var form = $(locationInput).closest('form');
        var street = form.find('#id_street');
        var postcode = form.find('#id_postcode');
        var city = form.find('#id_city');
        var country = form.find('#id_country');

        // if the location input isn't set, try to fetch GPS coordinates at document load
        if (!locationInput.val()) {
            update_map();
        }

        // update every time the text inputs change
        $([street, postcode, city, country]).each(function(){
            $(this).keyup(function() {
                update_map();
            });
        });

        // update every time the select changes
        $(country).change(function() {
            update_map();
        });

        function update_map() {
            // join all address parts values into single string
            var address = street.val() + ', ' + postcode.val() + ' ' + city.val() + ', ' + country.val();

            // initialize autocomplete service API
            var autocomplete_service = new google.maps.places.AutocompleteService();

            // try to find address prediction using autocomplete service API
            autocomplete_service.getPlacePredictions({input: address}, function (predictions, status) {
                // if status is incorrect, clear search value
                if (status != google.maps.places.PlacesServiceStatus.OK) {
                    $(widget.addressAutoCompleteInput).val('');
                    widget.deleteMarker();
                } else if (predictions.length >= 1) {
                    // otherwise if there is at least 1 prediction available, pick the very first one
                    var address_by_prediction = predictions[0].description;

                    // set the address as search value
                    $(widget.addressAutoCompleteInput).val(address_by_prediction);

                    // try to find the GPS coordinates of the predicted address
                    widget.geocoder.geocode({'address' : address_by_prediction}, function(results, status) {
                        if (status === google.maps.GeocoderStatus.OK) {
                            // check the successful result
                            var geo_location = results[0].geometry.location;
                            var latitude = geo_location.lat();
                            var longitude = geo_location.lng();

                            // add marker to map
                            widget.addMarkerToMap(latitude, longitude);
                            widget.updateLocationInput(latitude, longitude);

                            // set center position (or fit bounds)
                            widget.map.setCenter({lat: latitude, lng: longitude});
                            // widget.fitBoundMarker();

                            // set zoom (change according your needs or use bounds if you wish)
                            widget.map.setZoom(15);

                        } else {
                            // geocoder couldn't find a GPS...
                            widget.deleteMarker();
                            console.warn("Cannot find " + address_by_prediction + " on google geo service.")
                        }
                    });
                }
            });
        }
    }
})(jQuery || django.jQuery);

It works perfectly for me. Hope it helps you.

0reactions
josezycommented, May 9, 2019

ok, i know is more a django issue but thanks for the reply 😃

this is my TEMPLATE setting:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [TEMPLATES_DIR],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

with TEMPLATES_DIR = os.path.join(BASE_DIR, 'templates') which translates to ‘/home/monadical/pennybags/pennydjango/templates’. And is in that templates folder where I create another folder mapwidgets and put the template my_template.html.

Anyway, I found that I could use javascript triggers to catch the place_changed event (which is not explict in docs) and with that I could grab the autocompleted address. That was what I needed in first place.

Thanks for the help, is a cool widget 😸

Read more comments on GitHub >

github_iconTop Results From Across the Web

Place Autocomplete Address Form | Maps JavaScript API
The Place Autocomplete Address Form sample captures selected address components from the Google Places database, and uses them to populate an address form....
Read more >
How to make an autocomplete address field with google maps ...
Use script file to load the autocomplete class. Your scripts.js file will look something like this. // scripts.js custom js file $(document).
Read more >
jQuery UI and Auto-Complete Address Entry - I Programmer
The autocomplete widget allows you to specify a URL that it will get a JSON or JSONP response. In this case it doesn't...
Read more >
Adding an Auto-Complete Address Field to your Forms
This article shows you how to add auto-complete to any form requiring an address. By doing so, you improve the user experience while...
Read more >
Let's make a form that puts current location to use in a map!
A potential solution: get the address automatically · Get the HTML button and listen for a click event · Get the user's location...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found