9

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,

Community
  • 1
  • 1
tchap
  • 3,412
  • 3
  • 29
  • 46

2 Answers2

8

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>
Jason Fox
  • 5,115
  • 1
  • 15
  • 34
  • A note that the API Reference for **Feature.load** has apparently moved to [here](http://developer.here.com/javascript-apis/documentation/maps/topics_api_pub/nokia.Features.html). – Veksi Oct 04 '14 at 09:29
  • Also noteworthy is that loading features has changed in since beginning of version 3. More information at http://developer.here.com/documentation/versions. – Veksi Oct 04 '14 at 10:05
  • 1
    @Veski - I've updated the answer to clarify that the new **3.x** is version is much easier to load asynchronously. I would not encourage the continued use of the deprecated **2.x** in new projects – Jason Fox Oct 06 '14 at 07:38
  • Indeed, it may be prudent to start using the 3.n API these days. Though I think it could be helpful to have the 2.n way of doing things here too as almost all the examples at Here and GitHub are about the 2.n API. And at least I'm struggling enough with the 3.n version that, for the time being, 2.n might be a more appropriate choice (for my hobby projects). – Veksi Oct 07 '14 at 18:58
  • The **Feature.load** link gives HTTP 404. – Veksi Oct 11 '14 at 20:48
  • Answer straight from Nokia, and very detailed! – Christopher Marshall Dec 09 '14 at 22:23
  • I'm using jsp and struts, do I just need to include the require function in my javascript file and requirejs.config file in my jsp file. or do i need to download requirejs or add it as a script to my jsp file – 3rdeye7 Jul 24 '15 at 16:32
  • You should aim for a structure like https://github.com/volojs/create-template - as you can see the requirejs library is loaded in a – Jason Fox Jul 24 '15 at 18:47
2

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.

Loris Guignard
  • 131
  • 2
  • 5
  • Hello, I am developing one app with MH5 to integrate nokia maps in iOS and Android. I want to have a draggable marker so is it possible in mh5 or by jHERE pluggin. – user869123 Feb 18 '13 at 05:59