FAQs

Getting started

What is the mapsuite Javascript API?

By using the mapsuite Javascript API you can embed maps in your websites both for desktop and mobile browsers. You can control the visible section of the map by setting a set of coordinates or address, define user interaction with the map, add layers with Points of Interest (POIs), search hits or areas, calculate routes and visualize them on the map, and much more. Have a look at our tutorial for a brief overview of the API features.

The API and implementation is plain Javascript, so map applications created using the MapAPI run in all modern browsers without plugins, addons etc. All you need to start is basic Javascript knowledge.

What's the latest stable version?

The latest stable version is MapAPI 1.3.

Why should I use the mapsuite Javascript API?

We think you have plenty of reasons:

  1. No hosting or special server infrastructure required
  2. Start creating mapping applications without prior knowledge in mapping technologies
  3. Additional GIS-services like routing, geocoding, and coordinate projection
  4. Lots of powerful GUI controls and utility functions
  5. Easily extendable, e.g. to implement custom controls
  6. Configurable behavior and appearance of Points of Interest (POIs)
  7. Freely customizable map style
  8. Easy integration into existing web applications

What browsers are supported by the API?

Generally you should be able to use any current desktop browser. The infoware mapsuite Javascript API is tested in these browsers:

MapAPI 1.3

BrowserVersion
Mozilla FirefoxCurrent version
Google ChromeCurrent version
Microsoft EdgeCurrent version
Apple SafariCurrent version
OperaCurrent version
Microsoft Internet Explorer11.0

MapAPI 1.2

BrowserVersion
Mozilla FirefoxCurrent version
Google ChromeCurrent version
Microsoft EdgeCurrent version
Apple SafariCurrent version
OperaCurrent version
Microsoft Internet Explorer9.0

MapAPI 1.1

MapAPI 1.1 is fully compatible with the browsers MapAPI 1.0 is compatible with. In addition, mobile devices like smart phones and tablets are supported, too. On Android both the internal browser and Chrome are supported.

MapAPI 1.0

BrowserVersion
Mozilla Firefox3.0+
Apple Safari3.1.2+
Google ChromeCurrent version
Opera10.0+
Microsoft Internet Explorer6.0+

Does the API support mobile devices?

Yes, starting with version 1.1 both iOS (iPhone and iPad) and Android (Webkit based browsers for smart phones and tablets, like the default browser and Chrome) are supported.

These touch gestures can be used to control the map:

  • Moving the map by dragging with one finger ("drag")
  • Zooming the map with two fingers ("transform")
  • Showing POI details etc. by touching the map ("tap")
  • Zooming into the map by double tapping
  • Zooming out of the map by tapping with two fingers
  • Additional features like geocoding, searching etc. by holding the map

Please note that Android does not support multi touch events in browsers before version 3 ("Honeycomb").

Does the API support HTTPS URLs?

Yes, this is possible with this version of the MapAPI. It automatically switches to HTTPS transport if it is loaded by HTTPS.

Do I need server hardware to host a mapping application?

The API is usually hosted on our servers, so no more hardware resources are required on your side. All our servers are hosted in Germany to provide fast access in Europe.

However if you want to use your own server infrastructure, please contact us at support@infoware.de.

What is a VNR and a PNR, and how do I get them?

VNR and PNR are numbers used to identify a customer and product. Please contact us to get a valid VNR and PNR for your application/website.

How can I get help to use the API on my site?

There is a lot of description available here. If you still have questions please send us an email atsupport@infoware.de. Please feel free to contact us if you need any specific feature of the API which isn't available yet. We will see what we can do for you.

How do I report a bug?

Just send us an e-mail to support@infoware.de. Please include the following details:

  • A detailed description how to reproduce the bug if possible
  • System details (OS and browser including version)
  • The URL of the API you are using
  • The URL of your application if possible
  • A screenshot if necessary

How do I migrate an application from MapAPI 1.2 to 1.3?

In general we tried to make the MapAPI 1.3 as compatible as possible. Most applications can be ported with no or few changes by changing the URL to the new version. You'll probably want to make more changes to use some of the new features like the new IWMarkerFactory, accent color or IWLocationSearchControl.

See release history for a complete list of changes.

Here is a list of changes which could break compatibility with your application:

  • Extensive changes were made to the style sheets. Please check your application carefully to ensure that these do not conflict with your own CSS.
  • We have removed code for optical zoom in very outdated browsers that do not support CSS transitions or transform.
  • We have removed some obsolete classes with version 1.3. In the unlikely event that you have used them, you need to update your application to use the classes IWSVGToolbarControl (replaces IWToolbarControl) and IWLocationSearchControl (replaces IWCoordinateWindowControl and IWAddressSearchOneLineControl).

How do I migrate an application from MapAPI 1.1 to 1.2?

In general we tried to make the MapAPI 1.2 as compatible as possible. Most applications can be ported with no or few changes by changing the URL to the new version. You'll probably want to make more changes to use some of the new features like the new routing module or vector tiles.

Here is a list of changes which could break compatibility with your application:

  • Loading the API via mapping.js is no longer supported. More details on initializing the API core and modules can be found in chapter Basics.
  • IWXMLHttpRequest was used for backward compatibility with very outdated browsers and has been removed. If your application used this class, please replace it by IWXMLHttpRequest.
  • The module routing was completely reworked. If your application uses the classes IWRoutingControl or IWMultiControl, it should work without changes, but have a look at the tutorial chapter on Routing. If you use IWRoutingClient, please see the tutorial and IWRoutingManager to replace that.
  • Mouseover events on the driving directions show a tooltip of the direction in the map, replacing the "route magnifier" popups. Thus, IWRoutingMagnifierFactory has been removed from the API.
  • Some deprecated classes have been removed: IWVMLRenderer, IWBingCulture, and IWBingProjection are no longer available. These were used internally, the change should not affect your application.

How do I migrate an application from MapAPI 1.0 to 1.1?

In general we tried to make the MapAPI 1.1 as compatible as possible. Most applications can be ported with no or few changes by changing the URL to the new version. You'll probably want to make more changes to use some of the new features like touch gestures, modularization or geolocation.

Here is a list of changes which could break compatibility with your application:

  • The methods of the abstract base classes IWControl, IWOverlay, and IWWindowOverlay are attached to the prototype now. If you extend one of these classes make sure you inherit like this:
    function CustomInfoBubble(map, coordinate, content)
    {
    	IWWindowOverlay.call(this, map, coordinate); /* call constructor of base class */
    	
    	// your contructor implementation
    }
    
    CustomInfoBubble.prototype = new IWWindowOverlay(); /* inherit methods of base class */
    
    CustomInfoBubble.prototype.aMethod = function()
    {
    	// ...
    };
    
    CustomInfoBubble.prototype.anotherMethod = function()
    {
    	// ...
    };
    
  • IWControls do no longer implement IWDraggable (dragging was deactivated by default anyway). If you did implement your own controls based on IWControl and these controls need drag and drop functionality, you have to inherit the methods from IWDraggable yourself.
    function CustomControl(map)
    {
    	IWControl.call(this, map, 'CustomControl');
    	IWDraggable.call(this, this.getContainer(), map.getContainer());
    	
    	// your contructor implementation
    }
    
    CustomControl.prototype = new IWControl();
    for (var property in IWDraggable.prototype)
    	CustomControl.prototype[property] = IWDraggable.prototype[property];
    
    CustomControl.prototype.aMethod = function()
    {
    	// ...
    };
    
    CustomControl.prototype.anotherMethod = function()
    {
    	// ...
    };
    
  • The (undocumented) methods meterToPixelXY, pixelToMeterXY and needsReloadXY have been removed from the projection classes. If your application uses this methods you have to replace them by meterToPixel, pixelToMeter and needsReload.
  • Deleted class IWBrowserDetect. Browser detects are not reliable and should not be used. Please check for features instead of browsers for a more robust soluting. Example:
    if (navigator.geolocation && navigator.geolocation.getCurrentPosition)
    {
    	// feature is available
    }
    else
    {
    	// use a fallback
    }
    
  • log4javascript is no longer included in the MapAPI scripts. If you use log4javascript loggers in your application you have to include it yourself.
  • IWCloneable was renamed to IWClonable. Only affects appliactions with own classes which implement IWCloneable.
  • IWMoveEvents have been replaced by plain objects. Only applications which created IWMoveEvents or used instanceof / typeof operators to check for event types are effected by this.
  • Deleted class IWDistanceFormatter; use IWMeasuringControl.formatDistance() instead if your application did use this functionality.

Loading the API

How do I include the API in my application?

The easiest way is to include the core.js, which contains the mapping parts themself, base classes and interfaces, the event system etc. Just insert

<script type="text/javascript" src="js/core.js?vnr=[yourVNR]&pnr=[yourPNR]"></script>
into your page and start using the API after an onload event (or $(document).ready(yourInitHandler) when using jQuery). Other features like special controls, routing, or touch events for mobile devices, are available in modules. Just load the modules you want to use to reduce the loaded script size.

How do I load modules?

Replace your request to mapping.js by core.js to load the core module. Now identify the modules you want to use and add this code after the initialization of the map:

IWEventManager.addListener(IWLoader, 'onmoduleload', function(event)
{
	if (event.name == 'touch')
	{
		// touch module has been loaded, so add touch gestures to the map
		if (IWTouchUtils.isTouchScreenAvailable())
		{
			IWTouchUtils.addTouchGestures(map);
			IWTouchUtils.setTouchOptions(map, { autoClearTiles: true, reloadOnMove: false });
		}
	}
	else if (event.name == 'controls')
	{
		// control module has been loaded, so add some controls to the map
		var layer = map.getLayoutManager().getLayer(0); 
		layer.addControl(new IWZoomButtonControl(map), IWAlignment.BOTTOM, IWAlignment.LEFT, 0, 0);
		layer.addControl(new IWBirdsViewControl(map), IWAlignment.BOTTOM, IWAlignment.LEFT, 10, 10);
	}
});

// request the loading of two modules
IWLoader.loadModules(['touch', 'controls']);

A detailed example can be seen in mobile.html.

What modules are available?

  • controls This module contains most of the controls like the zoom slider, the scalar, the distance measuring tool, and the overview map. You will probably want to use this module unless you write a very basic application or write your own controls.
  • geocoding This module contains classes for geocoding and reverse geocoding requests.
  • graphics This module contains renderers to draw vector graphics like polygons, polylines, circles and rectangles on the map using SVG or HTML canvas.
  • navigation This module is intended to be used for basic navigation functionality in the future. At the moment it contains nothing but the GeoLocation API.
  • routing This module contains classes to calculate routes and display them on the map. To route from one address to another one requires geocoding the addresses, so you will need this module, too.
  • poi This module contains classes to support all kinds of points of interest (POIs) on the map.
  • touch This module contains classes to extend the map controls to touch gestures (move, transform, tap, double tap and hold) for mobile devices. Up to now iOS and Android (multitouch starting with Android 3) are supported.
  • selection This module contains classes to get access to special layers with selection logic (a demo is here).
  • geometryfilter This module contains classes to filter special layers by area or attributes

Usage and Examples

How can I change the mouse wheel function?

The default behavior zooms into the map on mouse wheel up events and out of the map on mouse wheel down.

If you want to change this for some reason you must disable the default behavior and implement your own handler method. Have a look at the example below which switches zooming directions:

map.getOptions().setMouseWheelAction(IWMapOptions.CONTROL_NONE);

var adapter = new IWMouseWheelAdapter(map, map.getContainer());
IWEventManager.addListener(adapter, 'onmousewheel', function(event)
{
	if (event.delta < 0)
		map.zoomIn();
	else
		map.zoomOut();
});

How can I use a full-window map which resizes with the window?

If you want a map to fit the window size, you can use the auto resize option. When set to true, the map will always fit the whole browser window.
var map = new IWMap(document.getElementById('map'));
map.getOptions().setSize(iw.windowSize()); // initialize the map with the window size 
map.getOptions().setAutoResize(true); // use auto resize to always fit the window

How can I limit the minimum and maximum map zoom?

Each map type can be configured by the methods setMinLevel, setMaxLevel and setPreferredLevel. The example below shows how to limit both the minimum and maximum level. In the last line setCenter is called to assure the map shows a valid zoom level (the old level may be out of the new constraints).

map.getCurrentMapType().setMinLevel(5);
map.getCurrentMapType().setMaxLevel(10);
map.getCurrentMapType().setPreferredLevel(8);
map.setCenter(map.getCenter(), map.getZoom());

How can I use features from the Kartenverzeichnis-API in my existing MapAPI application?

Using the Kartenverzeichnis-API in a MapAPI application is easy. Just first import the mapsuite API and then the Kartenverzeichnis-API in your page as seen in our example.

As the main class SearchableMap extends IWMap, all your existing code will run without changes after switching to SearchableMap. Just have a look at our test application on how to add more features.

I want to display multiple markers on the map. How can I choose the map view so that all markers are visible?

Below is a code snippet. For more details, please have a look at the documentation of IWBounds.

var nw = new IWCoordinate(6.85465, 51.08357, IWCoordinate.WGS84).toMercator(); // north-west of Cologne	
var se = new IWCoordinate(7.20694, 50.64929, IWCoordinate.WGS84).toMercator();	// south-east of Bonn
var myBounds = new IWBounds(nw, se);
	
var coord = new IWCoordinate(7.14512, 50.70001, IWCoordinate.WGS84).toMercator();  
myBounds.extendBy(coord);

map.setCenter(myBounds.getCenter(), map.getBoundsZoomlevel(myBounds));

In this example an existing bounds object is extended by another coordinate. If you have an array of coordinates just span a bounds object from the first two and extend it by all of them. Thus you will get a bounds object containing all your coordinates.

In case of a route you can use the bounds object of the route:

map.setCenter(route.getBounds().getCenter(), map.getBoundsZoomlevel(route.getBounds()));

Can I use the IWRoutingControl in an element which is not part of the map?

Yes, the IWRoutingControl can be attached to an element of your choice, e.g. to display it in a sidebar, a modal or below the map.

In this case you have to trigger the functions IWRoutingControl.beforeAppend() and IWRoutingControl.afterAppend() yourself:

let control = new IWRoutingControl(map, { /* your options */ });
let container = document.getElementById('yourContainer');

control.beforeAppend();
container.appendChild(control.getContainer());
control.afterAppend();

Can I change the rendering style of the route?

Yes, starting with version 1.1.46 you can set the rendering method to render by calling IWRoutingControl.setOptions(). This will render the route as a polyline in an IWMapRenderer, so all rendering attributes for polylines can be used:

var options = {
	render: 'renderer',
	renderAttributes: {
	stroke: 'green',
	strokeDashStyle: 'solid',
	strokeWidth: 5,
	strokeOpacity: 0.8
	}
};

var routingControl = new IWRoutingControl(map);
routingControl.setOptions(options);

IWMapRenderer is part of the module graphics, so you will have to load this module as well!

Which coordinate projection should be used?

MapAPI offers several projection-systems to describe positions on a map. The most important systems are:

WGS84 consists of a latitude value and a longitude value to define a certain point on earth. These values base on a spherical shape of the earth. WGS84 is often used to exchange position data between different system. For example, when you get position data from a GPS device.

Note: GPS uses the number format DD.HHMMSS, WGS84 here is used as decimal degrees.

Example: The address "Riemenschneiderstr. 11 in 53175 Bonn" has the WGS84 coordinate lon=7.141260 lat=50.701184, 6 decimal digits is a precision of approx. 1 meter.

Because the WGS84 system is spherical based, it has to be projected to get position data, that fits a planar view (on screen or printer). Map data itself is based on a planar metric system:

MERCATOR coordinates consist of a x-value and a y-value, both in meters. It is easier to use than WGS84: It can be directly mapped on a map (linear scale to pixels), it is easy to calculate distances (Pythagoras: distance = sqrt ( a^2 + b^2 )). This system is also used by other mayor map vendors.

Example: The address "Riemenschneiderstr. 11 in 53175 Bonn" has the MERCATOR x=794961 y=6568605 (metres).

See also the entries in english or german Wikipedia for further information.

My data is using a coordinate projection called LCC. Can I use this with the MapAPI?

Very old versions of our API did use Lambert conformal conic projections (LCC) called LCC Europe and LCC Germany / LCC TAO. These can still be used in the MapAPI. However, they must be projected to Mercator or WGS84 before use. This can be done with the class IWProjectionClient:

const projectionClient = new IWProjectionClient();
const coordinate = new IWCoordinate(-248539, -200); // location of Cologne main station in LCC TAO
projectionClient.project(coordinate, 'LCC_TAO', 'Mercator'); // project from LCC TAO to Mercator

IWEventManager.addListener(projectionClient, 'onprojection', function(event) {
    if (event.status === 'OK') {
    	// coordinate was projected successfully
		map.setCenter(event.outputCoordinate);
	}
});

How can I set the padding independently from other control-elements?

If you want to change the padding of a specific control-element, without affecting other controls, place it in a different layer than the other controls are in. However, this removes the ability to dock them to each other.

Another way to achieve this, is to wrap the control-element in a panel. The class IWPanelControl creates a 'layer within another layer', so you can use the same positioning like in the main-layer.

const layer = map.getLayoutManager().getLayer(0);
const panel = new IWPanelControl(map, new IWSize(100, 50));

let zoomButtonControl= new IWZoomButtonControl(map);

layer.addControl(panel, IWAlignment.BOTTOM, IWAlignment.LEFT, 0, 0);
panel.getLayoutManager().getLayer(0).addControl(zoomButtonControl, IWAlignment.RIGHT, IWAlignment.BOTTOM, 0, 0);

Now you have the panel docked to the bottom-left of the window. Inside the panel you have the IWZoomButtonControl, docked to the bottom-right.

To position the control-element further, you can modify the size of the IWPanelControl (e.g. 100 x 50), and dock the control-element accordingly. (Please refer to the Controls section of the tutorial for a detailed explanation.)

Other controls can now be docked to the panel, without the danger of overlapping with other controls:

let scalarControl = new IWScalarControl(map);
layer.addControl(scalarControl, IWAlignment.BOTTOM, IWAlignment.LEFT, 0, 15);

Map Types and Data

Which countries are covered by the API?

The MapAPI can be used with various providers of geodata, covering Germany, european and worldwide countries. Please contact us to find the best data source for your requirements.

Which map types are supported by the mapsuite API?

As of now mapsuite API supports roadmap, air, hybrid and bird's eye views. The map type is always set by a call to IWMap.setCenter(). To set a new map type, you can use this code snippet:

var type = map.getOptions().getMapTypeByName('hybrid');
map.setCenter(map.getCenter(), map.getZoom(), type);

For more details, please have a look at the documentation of IWMapType.

Is it possible to configure the appearance of the roadmap?

Yes, if you host your own map servers (which are part of the mapsuite) the layout can be configured in a very flexible way. We provide an application called MapStyler which may be used to design the map layout. Please contact us for more information.

How can I configure the categories and appearance of the POIs in the map?

The POIs are managed on backend servers. The selection of POI types, the appearance (i.e. the symbols), the zoom levels on which POIs are visible and more can be configured per application by a web application called MapCMS. Please contact us for details.

What are dynamic POIs and what types are available?

We have several types of dynamic POIs available with either dynamic content or dynamic coordinates (or both). Examples are traffic information, weather, filling stations, parking grounds and cinemas. Please contact us for more information.

Performance Optimization

How can I speed up tile loading?

The map is served as an image cut into several tiles. The browser aligns the tiles together back to a complete map. The tiles have to be loaded from the tile server. The number of tiles loaded depends on the screen size on the client and the number of border tiles which should be loaded additionally.

This number is usually greater than 20 on desktop machines. Standard browsers of today allow 6 parallel connections to one server; or to be more precise, to one subdomain of a domain. The other requests are queued. So the loading speed can be optimized by loading the tiles from different servers, and thus creating more parallel connections. For details please see Parallelize downloads across hostnames.

The MapAPI allows downloads from multiple servers. The load is spread equally among these servers. One tile is loaded always from the same server, so caching within the browser is fully used. To use multiple servers, or multiple subdomains on one server / server pool, you can configure aliases in the XML based MapAPI config file. For a MapAPI hosted on our servers, this already is configured.

How can I speed up map movement?

Usually map movement should be smooth and there is no need to tweak performance, unless you don't have to support very old browsers or hardware. If your map is to slow you should check if you are using time-consuming calculations on the onmove event of the map, which are fired everytime the map is moved for a single pixel. If this is the case you should check if it is possible to do this on the onmoveend event (which is fired when the map movement is done), so your calculation does not interfere with map movements.

Other settings you should check are the size of the map (is the map larger than the visible part you show on your page?) and the number of tiles which are loaded outside of the visible part of the map (see setBorderTiles(), usually should be 0 or 1).

How can I optimize the discarding of the tiles?

After the user moved or zoomed the map or changed the map type, new tiles are loaded and old tiles aren't visible any more. These tiles are not immediately removed from the DOM tree but are still available in background in case the user navigates back to this view. Tiles must be removed from the DOM tree because the browser cannot handle unlimited tiles. The strategy how tiles can be removed can be set manually. Three are available:

  • IWTilesRemovalStrategyHarsh is ideal for mobile devices. Because mobile devices have low memory everything which can be removed from the DOM is removed.
  • IWTilesRemovalStrategyNavigationDistance is the standard method for the desktop system. It preserves tiles the way the user is acting. If the user moves the map a lot tiles on the same layer are preserved. If the user switches the map types and zooms in and out tiles are preserved here.
  • IWTilesRemovalStrategyHeuristicCached is a strategy which flushes the cache from time to time and throws away tiles which are to far away from the center of the map. Additionally it preserves two zoom levels next to the current one.

The removal strategy of the map is defined like this:

map.setRemovalStrategy(new IWTilesRemovalStrategyHarsh());

Can I speed up the display of markers?

The MapAPI offers two ways to draw markers on the map. The base class IWOverlay can be used to attach DOM objects to a coordinate on the map. Everytime the map is moved or zoomed it updates these overlays. An example is the class IWMarker, but of course you can implement own classes which extend IWOverlay. Every overlay you add to the map is a DOM object, so adding lots (e.g. thousands) of these objects will result in slower map movements.

In this cases you should think of using layers. The markers in these layers are stored on the server and rendererd to a single image every time the map is moved. This is much faster for large amounts of markers. Examples for layers are POIs and routing layers.

For more detailed descriptions see the chapters on overlays and shapes in the tutorial.

Overlays Layers
numer of markers limited (depends on target plattform) huge amounts (managed on the server)
flexibility high (own implementations with HTML, JS, CSS) low (static images only)
user interaction fast (Javascript events) slow (round-trip-time to server)

Object-oriented Programming in Javascript

Do I have to use an object-oriented design for my application?

No, you don't have to. All features of the MapAPI can be used from procedural applications as well (unless you want to extend MapAPI classes, of course).

However, we suggest an object-oriented approach for complex applications as it leads to the same advantages as in other programming languages, like improved reusability, readability, testability and other benefits.

How does OOP work in Javascript?

If you are used to object-oriented languages like C++ or Java, OOP in Javascript won't look familiar to you. For example, there are no classes in Javascript but prototype-based inheritance. Here is a brief overview how OOP can be done with objects, constructor functions and prototypes. For a more detailed introduction see this article on MDN.

Step 1: Using constructor functions

The usual way to create an object in Javascript is var x = new Object(); (or the shorter notation var x = {};). The first step to introduce a "class" is to write a constructor function like this:

function Programmer(name)
{
	this.name = name;
	this.caffeine = 0;
}

When a constructor function is called with new, the newly created object becomes accessible in the function by the name this. Now you can create instances of your class by writing var x = new F();. The result is an object (typeof x will return 'Object') with the properties x and y.

Step 2: Adding methods to your class

As functions can be assigned to any variable, you can add functions as properties to your class to add methods. Again, use this to access the object and its properties from these functions:

function Programmer(name)
{
	this.name = name;
	this.caffeine = 0;
	
	this.work = function()
	{
		if (this.caffeine > 0)
		{
			console.log(name + ' produces some code');
		}
		else
		{
			throw name + ' is out of coffee!';
		}
	}
	
	this.drinkCoffee = function()
	{
		console.log(name + ' drinks coffee');
		this.caffeine += 5;
	}
}

var codeMonkey = new Programmer('Code monkey'); // now create an instance and use it
try
{
	codeMonkey.work();
}
catch (e)
{
	codeMonkey.drinkCoffee();
	codeMonkey.work();
}

Step 3: Using the prototype

Assigning the methods in the constructor has two main disadvantages: The constructor becomes more complex (thus making it slower) and the methods have to be assigned to each object which is instantiated from the class (imagine you need a lot of code monkeys...). A more elegant solution is to use the prototype of the constructor function instead:

function Programmer(name)
{
	this.name = name;
	this.caffeine = 0;
}

Programmer.prototype.work = function()
{
	if (this.caffeine > 0)
	{
		console.log(name + ' produces some code');
	}
	else
	{
		throw name + ' is out of coffee!';
	}
}

Programmer.prototype.drinkCoffee = function()
{
	console.log(name + ' drinks coffee');
	this.caffeine += 5;
}

How do I extend MapAPI classes?

There are some abstract base classes in the MapAPI which are meant to be extended. For example you can extend IWControl to implement your own controls or IWWindowOverlay to create your own bubbles to display content on the map. Other classes can be extended as well, for example think of an extended version of IWCoordinate which supports your custom coordinate projection.

To extend a class you have to do two steps: Make your constructor call the constructor of the base class, and create the prototype of your constructor as an instance of the base class. Let's have a look at this example:

function CustomCoordinate(x, y, projection)
{
	// TODO calculate lat, lon from x, y
	
	IWCoordinate.call(this, lon, lat, IWCoordinate.WGS84); // (1)
}

CustomCoordinate.prototype = new IWCoordinate(); // (2)

CustomCoordinate.prototype.toCustomProjection = function()
{
	var wgs84 = this.toWGS84();
	var lat = wgs84.getY();
	var lon = wgs84.getX();
	
	// TODO calculate x, y from lat, lon
	
	return new IWCoordinate(x, y, 'CustomProjection');
};

This class extends IWCoordinate to support a custom projection. To do this the lines marked with (1) and (2) are important. The first one calls the constructor IWCoordinate on the object "this", i.e. the object which is created by the CustomCoordinate constructor. For details see the documentation of Function.call().

The line marked with (2) makes the prototype of CustomCoordinate an instance of IWCoordinate, thus inheriting all methods and constants defined for IWCoordinate. Now you can use your custom coordinate class as replacement for IWCoordinate, i.e. map.setCenter(new CustomCoordinate(1234, 5678)); will center the map on the WGS84 position corresponding to the coordinate (1234, 5678) in your custom projection.