2

I have a form in my Rails app where I use the Google Places API for autocompletion, but I can't get it to work everytime. Every time you load the page where the form is, it's like a roll of dice: sometimes the JS works, sometimes it doesn't.

By the way, I have several other javascripts that also fails to work sometimes, but the ones for google autocomplete are the most quirky and they are mission-critical.

Here is the setup:

1° My html header has:

<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= yield :javascript_includes %>

Then in my body, I have the content_for tag that is yielded in the head

<% content_for :javascript_includes do %>
  <%= javascript_include_tag "application", "https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places" %>

  <script type="text/javascript">
     function initializeAutocomplete(){
       var input = document.getElementById('offer_location');
       var options = {
         types: ['(cities)']
       };

       var autocomplete = new google.maps.places.Autocomplete(input, options);

       google.maps.event.addListener(autocomplete, 'place_changed', function() {
         var place = autocomplete.getPlace();
         var lat = place.geometry.location.lat();
         var lng = place.geometry.location.lng();
         $('#offer_latitude').val(lat)
         $('#offer_longitude').val(lng)
       });
     }
     google.maps.event.addDomListener(window, 'load', initializeAutocomplete);
  </script>
<% end %>

I used to have the script with the initializeAutocomplete in a separate .js file that was loaded through the Asset Pipeline but that gave similar results: the autocomplete worked only half of the time... (in fact I feel it failed even more often)

I think the problem has to do with when the different elements are loaded, and when the callback is triggered. Here are examples of the things I tried to change :

  • using $(window).load and $(document).ready instead of addDomListener(window, 'load', initializeAutocomplete)

  • putting the script in a separate google-autocomplete.js file loaded in the Asset Pipeline (meaning it was loaded BEFORE the link to the API provided in the content_for tag

  • putting the script in a separate google-autocomplete.js file NOT included in the Asset Pipeline and called right after the API link tag in the content_for tag

Thanks a lot for your help!

-- EDIT --

In the end it turns out that it was turbolinks messing up with my jquery triggers, notably the one for google autocomplete. Found the answer there with which I fixed all my JS.

Community
  • 1
  • 1
  • I had the same issue - this worked for me http://ubilabs.github.io/geocomplete/examples/simple.html –  Sep 05 '14 at 11:44
  • Do you know what it does exactly? – user3778624 Sep 05 '14 at 15:10
  • Are you using Turbolinks in your project? If your scripts work when you first load the page, but not when you navigate to it using a link from another page within your website, then it's probably because of Turbolinks! – Olivier Lance Sep 08 '14 at 13:00
  • Yes I use turbolinks. Should I selectively turn it off for scripts that pose problem? Or turn it off for all Javascript? – user3778624 Sep 09 '14 at 08:23
  • It could be a render/loading issue. Try this ... http://stackoverflow.com/questions/10808109/script-tag-async-defer – icalvete Dec 15 '15 at 10:08

2 Answers2

0

Not sure if this addresses your actual bug but try calling the function with $(function() {initializeAutocomplete()}); - this is a neater alternative to $(document).ready(function(){

I would set it up like so:

<% content_for :javascript_includes do %>
  <%= javascript_include_tag "application", "https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places" %>

  <script type="text/javascript">
     function initializeAutocomplete(){
       var input = document.getElementById('offer_location');
       var options = {
         types: ['(cities)']
       };

       var autocomplete = new google.maps.places.Autocomplete(input, options);

       google.maps.event.addListener(autocomplete, 'place_changed', function() {
         var place = autocomplete.getPlace();
         var lat = place.geometry.location.lat();
         var lng = place.geometry.location.lng();
         $('#offer_latitude').val(lat)
         $('#offer_longitude').val(lng)
       });
     }
     $(function() {
       initializeAutocomplete();
     });
  </script>
<% end %>

so you define your function, then wait till the dom's finished loading.

This doesn't explain why it works sometimes and not others though. I would investigate by logging stuff out from the function with console.log()

Max Williams
  • 32,435
  • 31
  • 130
  • 197
  • I tried with the listener you suggested. It seems to work better but still not every time. when it fails on first page load, it usually works if I refresh. Does that give you any idea as to where the problem comes from? – user3778624 Sep 05 '14 at 15:07
  • Not really no. Try going down the logging route. – Max Williams Sep 05 '14 at 15:43
0

It could be a render/loading issue.

Try this...

<%= javascript_include_tag "https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=place", async: => true, :defer => true %>

Read more here ...

Script Tag - async & defer

Community
  • 1
  • 1
icalvete
  • 987
  • 2
  • 16
  • 50