Skip to main content
Ask A Question
Notifications
You’re not receiving notifications from this thread.
Subscribe

SEEKING FREELANCER - Javascript configuration

Javascript • Asked by Melanie

I have been trying for 4 years and 3 months to try to setup a basic rails app.

I have bought 10+ books, subscribed to this and several ohter subscription services to try to learn the basics of rails and javascript, posted hundreds of points in bounties on stack overflow and spent several thousand dollars on codementor.io / upwork and others in trying to ask for specific professional help in setting up a rails app to work with javascript. I cant understand why there isnt a basic guide that speaks to configuration (or if one exists, why it is so well hidden).

If anyone is available for paid work - to setup my app so that I can use javascript, in production, hosted on heroku with a rails 5 app, please could you let me know your rate and availability for a skype call to get this done.

I'm running out of steam to keep trying to learn to code. I've run down my rescources and am not clever enough to get past the basic configuration.

For background on all the things I've tried (just over this past year -now that I have started again with Rails 5), here is my most recent attempt:

http://stackoverflow.com/questions/41082357/rails-figuring-out-the-javascript-config

Thank you


Hmm ... I'm only briefly able to read your SO post don't have the time right now to go through it all the way.

From what I understand, the problem is that your code works on Development but not in Production? Is that right?

It might be a stupid question, but have you tried disabling turbolinks? Here's a link to how http://blog.flightswithfriends.com/post/53943440505/how-to-disable-turbolinks-in-rails-4 if you haven't tried it.

Sometimes, turbolinks will mess with you like you've mentioned in your post. If you haven't tried it, see if disabling it helps at all.

As I outlined in this post, the js files (except for google maps) don't work in production if I have the javascript include tag in the head. I only arrived at this solution after a long, expensive session on codementor. I can't afford another session to find out how to solve the problems that this solution has created. I also didn't get an explanation as to the fundamental reason why this change is necessary. The rails guides suggest including it there so I don't understand why, for the most part, moving it to the end of the body tag is a solution that gets the js to work in the production environment. This breaks the address js though, so it isn't the right solution

By reading through your JS, the reason that you need to load it at the bottom is because of the "getElementById" in the init()

var map = new google.maps.Map(document.getElementById('map'), {

By loading that at the top, the script might not find the element because it's loading before the element is created.

You could also try wrapping those in a document.onload handler to have it load after the DOM is done loading.


Hi John

Do you mean that I should write my address.js inside an event listener?

Thanks
Mel


I tried adding

document.addEventListener("turbolinks:load", function() {

to my google maps initialiser, but I still get the same problem.

I havent been able to find anyone on codementor.io or upwork that has been able to solve this configuration. None of my books, coursera programs, codeschool courses or the tutorials on this site address configuration. If you know of a resource that could help me to learn about what I need to do to configure a rails app so that I can use javascript, I'd really appreciate it.

I can see from this post [http://stackoverflow.com/questions/41435117/rails-5-how-to-use-javascript-in-production-on-heroku] that I'm imposing beyond my welcome on Stack Overflow and I'm reluctant to keep asking for help there - it hasnt been an effective way of solving this problem either. Perhaps ceejayoz is right - it's time to give up on trying to learn to code. I'm not intelligent enough to get step one sorted out.


Don't listen to people like that.

I mean't that you should comment out or remove turbolinks until your JS is working. If your other libraries are working, comment them out and just leave the one you're working on uncommented.

Your StackOverflow post is has become extremely long and in my opinion all over the place. Rather than me trying to figure out where you're at, tell me where you're at.

What's currently working and not working on your production environment app? Is it just Google Maps that's not working?


Oh, by the way, your application.js file isn't quite right...

You have:

//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require jquery-fileupload/vendor/jquery.ui.widget
//= require jquery-fileupload/jquery.iframe-transport
//= require jquery-fileupload/jquery.fileupload
//= require bootstrap-sprockets
//= require moment
//= require bootstrap-datetimepicker
//= require pickers
// require underscore
// require gmaps/google
//= require markerclusterer
//= require cocoon
//= require cable
//= require_tree .

Not that you're missing the equal signs on

// require underscore
// require gmaps/google

It should be:

//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require jquery-fileupload/vendor/jquery.ui.widget
//= require jquery-fileupload/jquery.iframe-transport
//= require jquery-fileupload/jquery.fileupload
//= require bootstrap-sprockets
//= require moment
//= require bootstrap-datetimepicker
//= require pickers
//= require underscore
//= require gmaps/google
//= require markerclusterer
//= require cocoon
//= require cable
//= require_tree .

That could be your issue right there...


I can either have googlemaps working (if I move the javascript include tag out of the head and to the end of the body tag) in which case, the rest of my javascript doesnt work.

Alternatively, I can use the rest of my javascript (except google maps) by includig the javascript include tag in the head tag - but then the google map doesnt render.

I tried removing turbolinks. I commented out all the files that refer to turbolinks and pushed that to production. I get no js errors showing in the console tab of the chrome inspector, but I also dont get a map - just a blank white square where the map should be.

Thanks very much for helping me.


I intentionally removed those two lines (underscore and gmaps). They were required when I was trying to use gmaps4rails gem but are not required to just use javascript. I couldnt get gmaps for rails gem to work. I found a solution that worked (although I couldnt set a zoom level) to render a map without that gem - so I removed the requirment for those 2 lines.


I can either have googlemaps working (if I move the javascript include tag out of the head and to the end of the body tag) in which case, the rest of my javascript doesnt work.

Yeah, don't do that. :)

Leave the JS tag in the header.

Try loading your address.js on the page itself instead. That's right, place it at the bottom of your views file.

I tried removing turbolinks. I commented out all the files that refer to turbolinks and pushed that to production

Leave turbolinks commented out until you figure this out.

I also dont get a map - just a blank white square where the map should be.

That means that the element is rendering correctly. Great!

You probably don't see the map because your javascript in your address.js file is being called before your element is rendered in the DOM.

Make sure your address.js code is after your map element in your view. That way, the javascript code runs after the element has been created.

I intentionally removed those two lines (underscore and gmaps). They were required when I was trying to use gmaps4rails gem but are not required to just use javascript. I couldnt get gmaps for rails gem to work. I found a solution that worked (although I couldnt set a zoom level) to render a map without that gem - so I removed the requirment for those 2 lines.

If you're no longer using it, I would just delete those lines.

In my opinion, if writing the code out is simple, try not to use gems. Everytime you add a gem, you add a dependency that could break and cause a LOT of headace in the future when trying to update rails.


I think when you say:

Make sure your address.js code is after your map element in your view. That way, the javascript code runs after the element has been created.

you mean that I need a listener in my address.js file.

That file currently has:

// document.addEventListener("turbolinks:load", function() {
function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 5
  });
  var bounds = new google.maps.LatLngBounds();
  // var opts = {
  //   zoom: 10,
  //   max_zoom: 16
  // }

  var n = addresses.length;
  for (var i = 0; i < n; i++) {
    var lat = addresses[i].latitude;
    var lng = addresses[i].longitude;
    if (lat == null || lng ==null){
      console.log(addresses[i].name + " doesn't have coordinates");
    }else {
      // var addresses = <%= raw @addresses.to_json %>,

      var address = new google.maps.Marker({
        position: {lat: parseFloat(lat), lng: parseFloat(lng)},
        title: addresses[i].name,
        map: map //,
//        zoom: 8
      });
      bounds.extend(address.position);
    }
  }
  map.fitBounds(bounds);
}

My view partial has:

<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=<%= ENV["GOOGLE_MAPS_API_KEY"] %>"
    async defer></script>
<%= javascript_tag do %>
  $(document).ready(function() {
    var addresses = <%= raw @addresses.to_json %>;
  });
<% end %>

I've replaced the turbolinks listener (because I've switched turbolinks off again) with a function to check if the document is ready.

I'm not sure if I am including the address.js file after the page loads by taking that step. It doesnt look like anything in the partial is specifically referencing address.js.

I tried this in production - I dont get any errors but I also get a blank white space instead of a map.


I don't mean add an event listener. I mean add it to the view file itself. You can organize your JS to be unobtrusive later. You want the code to run after the element is created. Place the function and the function call in a script tag beneath the map html element. Once you've done that, copy and paste the code you have for your view here.


So now my address.js has nothing in it and my views/addresses/_map.html.erb has:

<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=<%= ENV["GOOGLE_MAPS_API_KEY"] %>"
    async defer></script>
<script>
function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 5
  });
  var bounds = new google.maps.LatLngBounds();
  // var opts = {
  //   zoom: 10,
  //   max_zoom: 16
  // }

  var n = addresses.length;
  for (var i = 0; i < n; i++) {
    var lat = addresses[i].latitude;
    var lng = addresses[i].longitude;
    if (lat == null || lng ==null){
      console.log(addresses[i].name + " doesn't have coordinates");
    }else {
      // var addresses = <%= raw @addresses.to_json %>,

      var address = new google.maps.Marker({
        position: {lat: parseFloat(lat), lng: parseFloat(lng)},
        title: addresses[i].name,
        map: map //,
//        zoom: 8
      });
      bounds.extend(address.position);
    }
  }
  map.fitBounds(bounds);
}
</script>

<%= javascript_tag do %>
    var addresses = <%= raw @addresses.to_json %>;

<% end %>

The result in production is the same as before. A blank white space where the map placeholder is. No errors in the console tab of the chrome inspector.


Hmm. I just reordered a few things to load in the right order. I haven't tested your code...

Try this. Any errors in the console?

<div id="map"></div>

<script>
var addresses = <%= raw @addresses.to_json %>;

function initMap() {
    var bounds = new google.maps.LatLngBounds();
    var map = new google.maps.Map(document.getElementById('map'), {
        zoom: 5
        });

     var n = addresses.length;
     for (var i = 0; i < n; i++) {
         var lat = addresses[i].latitude;
         var lng = addresses[i].longitude;
         if (lat == null || lng ==null){
             console.log(addresses[i].name + " doesn't have coordinates");
         } else {
             var address = new google.maps.Marker({
                 position: {lat: parseFloat(lat), lng: parseFloat(lng)},
                 title: addresses[i].name,
                 map: map
                 });

        bounds.extend(address.position);
    }
  }

  map.fitBounds(bounds);
}
</script>

<script src="https://maps.googleapis.com/maps/api/js?key=<%= ENV["GOOGLE_MAPS_API_KEY"] %>"></script>

No console errors, but still a blank white space instead of a map. The address details populate to the script that I can see in the elements tab of the chrome inspector (as they do with the other variations on this).


Hmmm ... okay. I've tested your Javascript code because that would be the only issue here...

I've tested and refactored it outside of rails.

This works as a regular HTML file:

<!DOCTYPE html>
<html>
  <head>
    <style type="text/css">
        #map { width: 800px; height: 500px; }
    </style>

    <script src="https://maps.googleapis.com/maps/api/js?key=[YOUR_KEY_HERE]"></script>

  </head>
  <body>

    <div id="map"></div>

    <script>
    var map;

    // I'm guessing your address object structure here.
    var addresses = [
      {
        latitude: '30.2669444',
        longitude: '-97.7427778'
      },
      {
        latitude: '31.2669444',
        longitude: '-98.7427778'
      },
      {
        latitude: '29.2669444',
        longitude: '-96.7427778'
      }
    ];

    function initMap() {
        var bounds = new google.maps.LatLngBounds();

        var mapOptions = {
          zoom: 5,
          center: {lat: 30.2669444, lng: -97.7427778},
          mapTypeId: google.maps.MapTypeId.ROADMAP
        }

        var mapDiv = document.getElementById('map')

        map = new google.maps.Map(mapDiv, mapOptions);

         var n = addresses.length;
         for (var i = 0; i < n; i++) {
             var lat = addresses[i].latitude;
             var lng = addresses[i].longitude;
             if (lat == null || lng ==null){
                 console.log(addresses[i].name + " doesn't have coordinates");
             } else {
                 var address = new google.maps.Marker({
                     position: {lat: parseFloat(lat), lng: parseFloat(lng)},
                     title: addresses[i].name,
                     map: map
                     });

            bounds.extend(address.position);
        }
      }

      map.fitBounds(bounds);
    }
    // Make sure you call the initMap function
    initMap();
    </script>

  </body>
</html>

You may want to try model something similar in your rails view.

A couple of notes here:

  1. Make sure you have CSS that sets your height and width of the map element.
  2. Make sure you actually call your initMap() function.
  3. You don't need to add 'center' to your mapOptions object but I did it anyway.
  4. I moved the map api call to the header again. Feel free to do so.
  5. replace [YOUR_KEY_HERE] with your Google API key

Hi John

THANK YOU

Please can I pay you for the time you took to do this? I dont understand why the js cant be in the js folder but I'm beyond grateful that you found a way to make this work.

Thanks so much again.

Mel


Fantastic! No payment needed. :)

Now that's it's working, I'd recommend experimenting with a few things to clean the javascript up and make it unobtrusive.

  1. Try placing the Maps API Src call into the view partial itself. Be sure to place it above the address JS so that it runs first. This way, the maps api only runs on the pages that the map is loaded on.
  2. Try placing the address js back into the javascript file that you had so it's loaded with the rest of the asset pipline. Then, make sure your initMap() call is after the map HTML element is created.
  3. Try placing the initMap() call in a document ready function

If those don't work, no worries. You atleast have it working in the view with what you have now and can move forward with other features for your app.


Cool. I'll try it this afternoon. Thanks so much again.


Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 29,763+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.