2
\$\begingroup\$

My website has multiple pages that use the Google Maps api. Each page uses a different part of the api (e.g. autocomplete, displaying markers etc). However, every page needs to call the initMap() function for the api to be initialized. The logic that calls initMap() is controlled by google and it cannot take parameters.

maps.js

function initMap() {
  const mapOptions = {
    center: {lat: 0, lng: 0},
    zoom: 7
  };
  window.map = new google.maps.Map(document.getElementById("map"), mapOptions);

  if (typeof callback !== 'undefined') {
    callback(); // defined above html link to maps.js
  }
}

Instead of writing out a different initMap() function for every page, I opted to have it in one .js file which is linked to every page. After initializing the map, the function executes a callback function which is defined in each page's corresponding .js file.

index.js

function autocomplete() {
    var input = document.getElementById('address');
    new google.maps.places.Autocomplete(input);
}

As initMap() cannot take parameters, I had to define the callback function's name using a cross-script global variable before maps.js is linked. This variable is different on every page depending what function needs to be run in initMap() after the map is initialized.

<script type="text/javascript" src="js/index.js"></script>
<script> var callback = autocomplete </script> <!-- global variable, defines the callback function (in index.js) to initMap()(in maps.js) -->
<script type="text/javascript" src="js/maps.js"></script>

Is there a cleaner way to accomplish this?

\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

You can avoid the global by creating a closure around the function to be called by the maps api code. To do this define another function that returns a function. You can pass in the callback here.

The below code is runnable in single file but you will need to split it across pages in your real code.

function createInitMap(callback){
    return () => {
        const mapOptions = {
            center: {lat: 0, lng: 0},
            zoom: 7
        };
        window.map = new google.maps.Map(document.getElementById("map"), mapOptions);
    
        if (typeof callback !== 'undefined') {
            callback();
        }        
    }
}

/*
    In first page
*/
//<script type="text/javascript" src="js/index.js"></script>
let initMap = createInitMap(() => console.log('first callback'));
//<script type="text/javascript" src="js/maps.js"></script>

initMap(); // simulate google maps calling your function

/*
    In second page
*/
//<script type="text/javascript" src="js/index.js"></script>
initMap = createInitMap(() => console.log('second callback'));
//<script type="text/javascript" src="js/maps.js"></script>

initMap();  // simulate google maps calling your function

Ensure the return value of the function is assigned to the global name initMap (It might need to be window.initMap).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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