Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asynchronously loading Nokia Maps Javascript API

I'm trying to load the Nokia Maps javascript API asynchronously :

var oScript  = document.createElement('script');
oScript.type = 'text/javascript';
oScript.async = true;
oScript.src  = "http://api.maps.nokia.com/2.2.3/jsl.js?with=maps,positioning,placesdata";
document.body.appendChild(oScript);

As per expected, it doesn't work right away, so I tried overriding document.write thinking that could be the problem, to no avail (for instance, I did this https://stackoverflow.com/a/7884407/1741150).

The error I come across is that basically nokia.maps.map is not defined (hence, I cannot create a map using :

new nokia.maps.map.Display();

Is there a way to do this, or anybody has ever managed to do so ? I might be missing something

EDIT : I'm actually trying to write the script asynchronously in the page, not creating the map asynchronously (which is not a problem of course)

Thanks,

like image 924
tchap Avatar asked Dec 17 '12 21:12

tchap


2 Answers

HERE Maps API for JavaScript (3.0)

The newer 3.0 HERE Maps API for JavaScript is nicely modular, and fully supports asynchronous loading. For example it is possible to use requirejs to load a simple map as follows:

  require(['mapsjsService','mapsjsEvents', 'mapsjsUi'], function () {

      var platform = new H.service.Platform({
          app_id: '<YOUR APP ID>',
          app_code: '<YOUR TOKEN>'
      });
      var defaultLayers = platform.createDefaultLayers();
      var map = new H.Map(document.getElementById('map'),
        defaultLayers.normal.map);
      var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
      var ui = H.ui.UI.createDefault(map, defaultLayers);
    });

The configuration file needs to be assigned as follows:

 requirejs.config({
    baseUrl: '.',
    waitSeconds: 0,
    map: {
      '*': {
        'css': 'require-css' // or whatever the path to require-css is
      }
    },
    paths: {
        'mapsjsCore' : 'https://js.api.here.com/v3/3.0/mapsjs-core',
        'mapsjsService' : 'https://js.api.here.com/v3/3.0/mapsjs-service',
        'mapsjsEvents' : 'https://js.api.here.com/v3/3.0/mapsjs-mapevents',
        'mapsjsUi' :'https://js.api.here.com/v3/3.0/mapsjs-ui',

        'mapsjsCss' :'https://js.api.here.com/v3/3.0/mapsjs-ui',
      },
      shim: {
        'mapsjsService': {
          deps: ['mapsjsCore']
        },
        'mapsjsEvents': {
          deps: ['mapsjsCore']
        },
        'mapsjsUi': {
          deps: ['mapsjsCore', 'css!mapsjsCss']
        }
      }
    });

As can be seen, all modules rely on the mapsjsCore, but none of the sub-modules rely on each other. The mapsjsUi is a special case as it has an associated CSS file for the default look-and-feel. You can either hold the default CSS (or your override) in the header, or alternatively load it using a requirejs plug-in such as require-css. It should be noted that the line waitSeconds:0 is required in the config to avoid a timeout when downloading the HERE Maps for JavaScript libraries to a browser for the first time since they will not be found locally, so you are reliant on the speed of your internet connection at least once.

Or alternatively with Jquery:

$.getScript('https://js.api.here.com/v3/3.0/mapsjs-core.js', function() {
  $.getScript('https://js.api.here.com/v3/3.0/mapsjs-service.js', function() {
    $.getScript('https://js.api.here.com/v3/3.0/mapsjs-mapevents.js', function() {
      $.getScript('https://js.api.here.com/v3/3.0/mapsjs-mapevents.js', function() {
        ////
        //
        // Don't forget to set your API credentials
        //
        var platform = new H.service.Platform({
          app_id: 'DemoAppId01082013GAL',
          app_code: 'AJKnXv84fjrb0KIHawS0Tg',
          useCIT: true
        });
        //
        //
        /////
        var defaultLayers = platform.createDefaultLayers();
        var map = new H.Map(document.getElementById('map'),
          defaultLayers.normal.map, {
            center: {
              lat: 50,
              lng: 5
            },
            zoom: 4
          });
        var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
        var ui = H.ui.UI.createDefault(map, defaultLayers);
      });
    });
  });
});
body {
       margin: 0;
       padding: 0;
     }

     #map {
       width: 100%;
       height: 100%;
       position: absolute;
       overflow: hidden;
       top: 0;
       left: 0;
     }
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
  <link rel="stylesheet" type="text/css"
    href="http://js.api.here.com/v3/3.0/mapsjs-ui.css" />
</head>
<body>
<div id="map"></div>
</body>

 

Nokia Maps API for JavaScript (2.2.4-2.5.4)

The recently deprecated version of the Nokia Maps API for JavaScript (versions 2.2.4 and onwards) supports Asynchronous loading as shown below

The details can be found in the Feature.load method of the API Reference Feature.load has two callbacks one for success (where you can continue to add in your App ID and token, display the map and so on, and one for failure.

// this is our initial script that will load jsl.js
var oScript = document.createElement("script"),
  //once the jsl.js is load, we load all features
  onScriptLoad = function() {
    nokia.Features.load(
      // here we get all features (provide one or many "with" parameters
      nokia.Features.getFeaturesFromMatrix(["all"]),
      // an callback when everything was successfully loaded
      onApiFeaturesLoaded,
      // an error callback
      onApiFeaturesError,
      // a target document (or null if the current document applies)
      null,
      // a flag indicating that loading should be asynchronous
      false
    );
  },
  // once all features we loaded, we can instantiate the map
  onApiFeaturesLoaded = function() {

    /////////////////////////////////////////////////////////////////////////////////////
    // Don't forget to set your API credentials
    //
    // Replace with your appId and token which you can obtain when you 
    // register on http://api.developer.nokia.com/ 
    //
    nokia.Settings.set("appId", "YOUR APP ID");
    nokia.Settings.set("authenticationToken", "YOUR TOKEN");
    //          
    /////////////////////////////////////////////////////////////////////////////////////

    var mapContainer = document.getElementById("mapContainer");
    var map = new nokia.maps.map.Display(mapContainer, {
      center: [40.7127, -74.0059],
      zoomLevel: 13,
      components: [new nokia.maps.map.component.ZoomBar(),
        new nokia.maps.map.component.Behavior(),
      ]
    });
  },
  // if an error occurs during the feature loading
  onApiFeaturesError = function(error) {
    alert("Whoops! " + error);
  };

oScript.type = "text/javascript";
// NOTE: tell jsl.js not to load anything by itself by setting "blank=true"
oScript.src = "http://api.maps.nokia.com/2.2.4/jsl.js?blank=true";
// assign the onload handler
oScript.onload = onScriptLoad;

//finally append the script
document.getElementsByTagName("head")[0].appendChild(oScript);
     body {
       margin: 0;
       padding: 0;
     }

     #mapContainer {
       width: 100%;
       height: 100%;
       position: absolute;
       overflow: hidden;
       top: 0;
       left: 0;
     }
<!DOCTYPE html>
    <html>
        <head>
            <meta http-equiv="content-type" content="text/html; charset=utf-8">
            <title>Asynchronous Loading</title>
        </head>
        <body>
            <div id="mapContainer"></div>

       </body>
    </html>
like image 151
Jason Fox Avatar answered Nov 06 '22 15:11

Jason Fox


You should have a look at the jHERE library which will give you a slick async loading plus a bunch of cool other features if you want to play with the Nokia Maps API.

like image 2
Loris Guignard Avatar answered Nov 06 '22 15:11

Loris Guignard