Bing Maps v7 AJAX control Infobox positioning

In the Bing Maps v7 AJAX control, when you open an infobox it will open up where it is positioned. If you are near the edges of the map it will go beyond the edges and end up getting cut of, out of view as the infobox is within the map div which hides any overflowing elements. Here is an example.

infobox1

This might not be the ideal default case, but Bing Maps is developed in such a way that it tries to give you the basic use case and all the tools needed to create the experience you want. One way around this is to use the Custom Infobox Control module for Bing Maps that will change the direction of the infobox so that it appears towards the center of the map. This works well in some cases, but completely ignores the built in infobox control and requires jQuery.

For those migrating from Multimap you may prefer the map to reposition so that the infobox comes into view. This is a user experience that others would prefer as the infobox will always render in the same way. The following code uses the built in infobox properties to determine if the infobox needs to be repositioned and if it does it moves the map so that the infobox comes into view.

[php]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>

<script type="text/javascript">
var map = null;
var pinLayer, pinInfobox;

function GetMap() {
// Initialize the map
map = new Microsoft.Maps.Map(document.getElementById("myMap"), { credentials: "YOUR_BING_MAPS_KEY", zoom: 5 });

//Create two layers, one for pushpins, the other for the infobox. This way the infobox will always be above the pushpins.
pinLayer = new Microsoft.Maps.EntityCollection();
map.entities.push(pinLayer);

var infoboxLayer = new Microsoft.Maps.EntityCollection();
map.entities.push(infoboxLayer);

// Create the info box for the pushpin
pinInfobox = new Microsoft.Maps.Infobox(new Microsoft.Maps.Location(0, 0), { visible: false });
infoboxLayer.push(pinInfobox);

//Create a test pushpiin
var pin = new Microsoft.Maps.Pushpin(map.getCenter());
pin.Title = ‘This is pin 1’;
pin.Description = ‘Pan map so pin is at edge and then click on pin.’;

Microsoft.Maps.Events.addHandler(pin, ‘click’, displayInfobox);
pinLayer.push(pin);
}

function displayInfobox(e) {
if (e.targetType == "pushpin") {
pinInfobox.setOptions({ title: e.target.Title, description: e.target.Description, visible: true, offset: new Microsoft.Maps.Point(0, 25) });
pinInfobox.setLocation(e.target.getLocation());

//A buffer limit to use to specify the infobox must be away from the edges of the map.
var buffer = 25;

var infoboxOffset = pinInfobox.getOffset();
var infoboxAnchor = pinInfobox.getAnchor();
var infoboxLocation = map.tryLocationToPixel(e.target.getLocation(), Microsoft.Maps.PixelReference.control);

var dx = infoboxLocation.x + infoboxOffset.x – infoboxAnchor.x;
var dy = infoboxLocation.y – 25 – infoboxAnchor.y;

if (dy < buffer) { //Infobox overlaps with top of map.
//Offset in opposite direction.
dy *= -1;

//add buffer from the top edge of the map.
dy += buffer;
} else {
//If dy is greater than zero than it does not overlap.
dy = 0;
}

if (dx < buffer) { //Check to see if overlapping with left side of map.
//Offset in opposite direction.
dx *= -1;

//add a buffer from the left edge of the map.
dx += buffer;
} else { //Check to see if overlapping with right side of map.
dx = map.getWidth() – infoboxLocation.x + infoboxAnchor.x – pinInfobox.getWidth();

//If dx is greater than zero then it does not overlap.
if (dx > buffer) {
dx = 0;
} else {
//add a buffer from the right edge of the map.
dx -= buffer;
}
}

//Adjust the map so infobox is in view
if (dx != 0 || dy != 0) {
map.setView({ centerOffset: new Microsoft.Maps.Point(dx, dy), center: map.getCenter() });
}
}
}
</script>
</head>
<body onload="GetMap();">
<div id=’myMap’ style="position:relative; width:600px; height:400px;"></div>
</html>
[/php]

When you load this code into a browser a pushpin will appear in the center of the map. Pan the map so that the infobox is near one of the edges. When you click on the pushpin to open the infobox you will see the map reposition such that the infobox comes into view. The example below is the result of opening the infobox when the pushpin was in the top right corner of the map.

 

Bing Maps V7 Modules

The Bing Maps 7.0 Control was released last fall and is a complete rebuild from the ground up when compared to previous versions of Bing Maps. We have seen huge improvements in API performance and the size of the control. One feature of the map control is that it uses a modular framework, which allows you to register and load modular blocks of code as they are needed. This means that you are able to load in features only when they are essential, which results in faster loading speeds. Not only does this allow you to load in additional Bing Maps features and functionalities, but it also opens itself up for custom modules.

image

Creating a custom reusable module allows you to save time when making multiple applications since common blocks of code can be designed to be written so that they can be reused. By making code reusable, development time can be reduced. If the module is properly maintained it will also become better with time as bugs are fixed and optimizations added. But creating and maintaining a collection of modules may be a lot work for a single person.

Let us introduce the Bing Maps v7 Module CodePlex Project. This is a community site where people can share their modules for Bing maps. By having one central location for hosting these modules we make it easier for developers to find them and reduce the need to go searching through blogs for them. To date there are currently 4 modules that have been submitted for inclusion in the portal.

Module Name Description
Client Side Clustering This module allows you to easily add in clustering functionality into Bing Maps simply by using an extended version of the EntityCollection class called ClusteredEntityCollection.
Custom Infobox Control This module generates highly customizable infoboxes.
GeoRSS This module allows you to import GeoRSS files into Bing Maps. This module supports majority of GeoRSS and GML tags.
Simple GeoRSS This is a light weight module that can load a Simple GeoRSS feed to Bing Maps.

This project site also includes information on how to create and submit modules for inclusion in this site. If you have an idea for a module but are not sure where to start, add it to our list of module ideas here.