Chris Pietschmann

husband, father, hacker, entrepreneur, futurist, innovator, autodidact

NAVIGATION - SEARCH

Bing Maps Ajax 7: Adding InfoBox Support via Extension to Microsoft.Maps

The new Bing Maps Ajax v7 control may be faster and smaller, but it is pretty light on features at the moment compared to its older brother; the v6.3 control. One of the features missing is support for showing InfoBox’s. Its simple to handle mouse events and display a <div> next to the pushpin, but I thought I’d take a little time to write a simple InfoBox extension to the new Microsoft.Maps namespace.

Here’s a screenshot of it in action:

BingMaps7_InfoBox_Screenshot

Usage

Let’s start with some sample usage of the InfoBox extension.

// Create Pushpin
var pushpin = new Microsoft.Maps.Pushpin(
    new Microsoft.Maps.Location(0,0)
);

// Create InfoBox
var infobox = Microsoft.Maps.Ext.InfoBox(
    "Title", /* <-- InfoBox Title to display */
    "Description", /* <-- InfoBox Description to display */
    map /* <-- A refernce to the Map where the InfoBox will be displayed */
);

// Add InfoBox to Pushpin
pushpin.setInfoBox(infobox);

// Add Pushpin to Map
map.entities.push(pushpin);

Usage of the “Microsoft.Maps.Ext.InfoBox” object is fairly simple. After creating the InfoBox object, you assign it to the Pushpin via the “setInfoBox” method that is also an extension that has been added.

CSS

There is a small bit of CSS code needed to style the InfoBox appropriately.

Here’s some sample HTML that is similar to what the InfoBox extension adds to the page for the InfoBox’s:

<div class="infobox">
<h4>Title</h4>
Description
</div>

The <div> element is given the CSS class of “infobox”. You use this class name to add CSS to your application to style the InfoBox’s as desired.

Here’s some sample CSS to give the InfoBox a style similar to the Bing Maps v6.x InfoBox’s:

<style>
.infobox
{
    position: absolute;
    z-index: 10000;
    
    width: 150px;
    
    background: #fff;
    border: solid 1px #555;
    padding: 8px;
    color: #555;
}
.infobox h4
{
    color: #000;
    margin: 0;
    font-weight: bold;
}
</style>

Custom Pushpin Method Reference

Here’s some documentation of the 2 methods I added to the Microsoft.Maps.Pushpin object:

Pushpin.setInfoBox(infobox)
This method is used to set a specific InfoBox to be show for the Pushpin.

Pushpin.removeInfoBox()
This method is used to remove a previously added InfoBox from the Pushpin.

InfoBox Method Reference

Here’s some documentation on the Microsoft.Maps.Ext.InfoBox object:

Microsoft.Maps.Ext.InfoBox(title, description, map)
This is the constructor of the InfoBox object.

  1. title – The HTML to show in the InfoBox title area.
  2. description – The HTML to show in the InfoBox description area.
  3. map – A reference to the Map where the InfoBox’s Pushpin is located, and where it will be displayed.

InfoBox.title(title)
This method gets or sets the Title of the InfoBox. If an argument is passed in, it will set the Title and return the InfoBox object to allow for a fluent interface. If no argument is passed in, it will return the value of the InfoBox Title.

InfoBox.descirption(description)
This method gets or sets the Description of the InfoBox. If an argument is passed in, it will set the Description and return the InfoBox object to allow for a fluent interface. If no argument is passed in, it will return the value of the InfoBox Description.

Full InfoBox Extension

Rather than add the InfoBox object to the root of the “Microsoft.Maps” namespace, I decided to add the “Microsoft.Maps.Ext” namespace where the InfoBox object will live. This will help keep it separated from “core” Microsoft.Maps functionality. Now the only methods added to the “core” namespace are the “setInfoBox” and “removeInfoBox” methods that were necessary to add directly to the Pushpin object.

Requirements:
This extension requires jQuery to function.

I could have coded the necessary JavaScript code to manipulate the HTML DOM myself, but it was just easier to use jQuery. Plus, if you’re like me, you will probably be using jQuery in your application anyway so it wont add any additional download.

Source Code:
Now for the real meat of the post. Here is the full JavaScript code for the InfoBox extension.

(function ($m) {
    /* $m == Microsoft.Maps namespace */
    /* Add "Microsoft.Maps.Ext" namespace if it doesn't exist
    This is used to hold the custom InfoBox functionality */
    if (!$m.Ext) { $m.Ext = {}; }

    /* Microsoft.Maps.Ext.InfoBox extension */
    var InfoBox = $m.Ext.InfoBox = function (title, desc, map) {
        return new InfoBox.fn.init(title, desc, map);
    };
    InfoBox.prototype = InfoBox.fn = {
        init: function (title, desc, map) {
            this._element = null;
            this._title = title;
            this._description = desc;
            this._map = map;
        },
        title: function (v) {
            if (v !== undefined) {
                this._title = v;
                return this;
            }
            return this._title;
        },
        description: function (v) {
            if (v !== undefined) {
                this._description = v;
                return this;
            }
            return this._description;
        },
        show: function (e) {
            /* Get location of Pushpin */
            var loc = this.map().
                tryLocationToPixel(
                    e.target.getLocation(), Microsoft.Maps.PixelReference.page
                );
            if (this._element === null) {
                /* Create <div> to show as InfoBox */
                this._element = $('<div>').
                    addClass('infobox').
                    appendTo($(document.body)).
                    html('<h4>' + this.title() + '</h4>' + this.description());
            }
            /* Show InfoBox and set position*/
            this._element.show().css({
                position: 'absolute',
                /* offset the infobox a little */
                top: loc.y - 10,
                left: loc.x + 10
            });
        },
        hide: function () {
            /* Hide InfoBox from view */
            if (this._element !== null) {
                this._element.hide();
            }
        },
        map: function (v) {
            if (v) {
                this._map = v;
                return this;
            }
            return this._map;
        }
    };
    InfoBox.fn.init.prototype = InfoBox.fn;

    /* Microsoft.Maps.Pushpin extensions */
    (function (proto) {
        if (!proto.setInfoBox) {
            proto.setInfoBox = function (infoBox) {
                this.removeInfoBox();
                this.infobox = infoBox;
                /* attach event handlers */
                this.infoboxMouseOverHandler = $m.Events.addHandler(
                    this,
                    "mouseover",
                    function (e) {
                        infoBox.show(e);
                    });
                this.infoboxMouseOutHandler = $m.Events.addHandler(
                    this,
                    "mouseout",
                    function (e) {
                        infoBox.hide(e);
                    });
            };
        }
        if (!proto.removeInfoBox) {
            proto.removeInfoBox = function () {
                /* detach event handlers */
                $m.Events.removeHandler(this.infoboxMouseOverHandler);
                $m.Events.removeHandler(this.infoboxMouseOutHandler);
                this.infobox = null;
            };
        }
    })($m.Pushpin.prototype);
})(Microsoft.Maps);

Conclusion

I didn’t go over the specifics of writing this plugin too much. If you want to see more examples of what’s involved, then I recommend reading the “Creating Infoboxes in Bing Maps AJAX v7” post on MSDN Social.

blog comments powered by Disqus