Thursday, March 7, 2013

Bing Map integration with CRM 2011 - Search near by accounts

1. Create two fields on account entity; new_Latitude and new_Longitude
2. Palce the bing map key in the code
3. Add the html below as web resource
4. Add jquery_1_9_1_min.js web resource


<html><head><title>Bing Map</title>
<meta content="text/html; charset=utf-8?" http-equiv="Content-Type"/>
<script type="text/javascript" src="https://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>
<script type="text/javascript" src="new_jquery_1_9_1_min.js"></script>
<script type="text/javascript">
    var map = null;
    function GetMap() {
        Microsoft.Maps.loadModule('Microsoft.Maps.Themes.BingTheme', { callback: themesModuleLoaded });

    }

    function themesModuleLoaded() {
        // Initialize the map
        map = new Microsoft.Maps.Map(document.getElementById("mapDiv"), { credentials: "Add your Key here", mapTypeId: Microsoft.Maps.MapTypeId.road, theme: new Microsoft.Maps.Themes.BingTheme() });
    }

    function ClickGeocode(credentials) {
        map.getCredentials(MakeGeocodeRequest);
    }
    function MakeGeocodeRequest(credentials) {
        var query = "";
        //Get Address/Latitude and Longitude values from MS CRM account's form
        var lat = window.parent.Xrm.Page.getAttribute("new_latitude").getValue();
        var lng = window.parent.Xrm.Page.getAttribute("new_longitude").getValue();
        if (lat == null || lng == null) {
            lat = 40;
            lng = -100;
        } else {
            query = lat + ", " + lng;
        }
        var geocodeRequest = "https://dev.virtualearth.net/REST/v1/Locations/" + query + "?output=json&jsonp=GeocodeCallback&key=" + credentials;  
        CallRestService(geocodeRequest);
    }
    function GeocodeCallback(result) {
        if (result &&
                   result.resourceSets &&
                   result.resourceSets.length > 0 &&
                   result.resourceSets[0].resources &&
                   result.resourceSets[0].resources.length > 0) {
            // Set the map view using the returned bounding box
            var bbox = result.resourceSets[0].resources[0].bbox;
            var viewBoundaries = Microsoft.Maps.LocationRect.fromLocations(new Microsoft.Maps.Location(bbox[0], bbox[1]), new Microsoft.Maps.Location(bbox[2], bbox[3]));
            map.setView({ zoom: 5, center: new Microsoft.Maps.Location(result.resourceSets[0].resources[0].point.coordinates[0], result.resourceSets[0].resources[0].point.coordinates[1]) });
            //map.setView({ bounds: viewBoundaries });
            centerLocation = new Microsoft.Maps.Location(result.resourceSets[0].resources[0].point.coordinates[0], result.resourceSets[0].resources[0].point.coordinates[1]);

            var pushpin = new Microsoft.Maps.Pushpin(centerLocation);
            map.entities.push(pushpin);
         
        }
    }
    function CallRestService(request) {
        var script = document.createElement("script");
        script.setAttribute("type", "text/javascript");
        script.setAttribute("src", request);
        document.body.appendChild(script);
    }

 

    function pinAccounts() {
        var odataQuery = "accountSet?$select=name,new_Latitude,new_Longitude";
        map.entities.clear();
     
        var centerPin = new Microsoft.Maps.Pushpin(centerLocation, { text: "C" });
        map.entities.push(centerPin);
        var infoboxOptions = {
            title: "Account:",
            description: accountName,
            showPointer: true,
            showCloseButton: false,
            offset: new Microsoft.Maps.Point(0, 32),
            visible: false
        };
        var centerPinIB = new Microsoft.Maps.Infobox(centerLocation, infoboxOptions);
        boxes[projectPin.getText()] = centerPinIB;
        Microsoft.Maps.Events.addHandler(centerPin, 'mouseover', displayInfobox);
        Microsoft.Maps.Events.addHandler(centerPin, 'mouseout', hideInfobox);
        map.entities.push(centerPinIB);
        map.setView({ center: centerLocation });

        //Add Near by accounts
        var results = retrieveRecords(odataQuery);
        if (results != null && results.length > 0) {

            for (var i = 0; i < results.length; i++) {
                var lat = results[i].new_Latitude;
                var lon = results[i].new_Longitude;
                var location = new Microsoft.Maps.Location(lat, lon);
                var d = distance(projectLocation, location);
                var radius = jQuery("#milesText").val();

                if (radius.length > 0) {
                    if (Math.abs(d) <= Math.abs(radius)) {
                        var pushpin = new Microsoft.Maps.Pushpin(location, { text: results[i].name });
                        map.entities.push(pushpin);

                        infoboxOptions = {
                            title: results[i].name,
                            description: "NA",
                            showPointer: true,
                            showCloseButton: false,
                            offset: new Microsoft.Maps.Point(0, 32),
                            visible: false
                        };

                        var accInfobox = new Microsoft.Maps.Infobox(location, infoboxOptions);
                        map.entities.push(accInfobox);
                        boxes[pushpin.getText()] = accInfobox;

                        Microsoft.Maps.Events.addHandler(pushpin, 'mouseover', displayInfobox);
                        Microsoft.Maps.Events.addHandler(pushpin, 'mouseout', hideInfobox);
                    }

                }
                else {

                }
            }

        }
    }

    function retrieveRecords(odataQuery) {

        if (!odataQuery) {
            alert("odataQuery is required.");
            return;
        }

        //The XRM OData end-point
        var ODATA_ENDPOINT = "/XRMServices/2011/OrganizationData.svc";
        var serverUrl = _getServerUrl();
        var records;

        //Asynchronous AJAX function to Retrieve a CRM record using OData
        $.ajax(
{
    type: "GET",
    async: false,
    contentType: "application/json; charset=utf-8",
    datatype: "json",
    url: serverUrl + ODATA_ENDPOINT + "/" + odataQuery,
    beforeSend: function (XMLHttpRequest) {
        //Specifying this header ensures that the results will be returned as JSON.          
        XMLHttpRequest.setRequestHeader("Accept", "application/json");
    },
    success: function (data, textStatus, XmlHttpRequest) {
        records = retrieveRecordsCompleted(data.d, textStatus, XmlHttpRequest);
    },
    error: function (XmlHttpRequest, textStatus, errorThrown) {
        WEG.Xrm.errorHandler(XmlHttpRequest, textStatus, errorThrown);
    }
});
        return records;
    }
    function _getServerUrl() {
        var serverUrl = window.parent.Xrm.Page.context.getServerUrl();
        if (serverUrl.match(/\/$/)) {
            serverUrl = serverUrl.substring(0, serverUrl.length - 1);
        }
        return serverUrl;
    }
    function retrieveRecordsCompleted(data, textStatus, XmlHttpRequest) {
        return data.results;
    }
    function category(checkbox) {

        if (checkbox.checked) {
            categories.push(checkbox);
        }
        else
            categories.pop(checkbox);

    }

    function subCategory(checkbox) {
        if (checkbox.checked)
            subCategories.push(checkbox);
        else
            subCategories.pop(checkbox);
    }
     
    //Get distance between two locations
    function distance(location1, location2) {

        var lat1 = location1.latitude;
        var lon1 = location1.longitude;
        var lat2 = location2.latitude;
        var lon2 = location2.longitude;
        var earthRadius = 6371; //appxoximate radius in miles

        var factor = Math.PI / 180;
        var dLat = (lat2 - lat1) * factor;
        var dLon = (lon2 - lon1) * factor;
        var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1 * factor) * Math.cos(lat2 * factor) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        var d = earthRadius * c;
        return d;
    }

    function displayInfobox(e) {

        var pin = e.target;

        if (pin != null) {
            boxes[pin.getText()].setOptions({ visible: true });
        }
    }

    function hideInfobox(e) {
        var pin = e.target;
        var infobox = boxes[pin.getText()];
        if (pin != null) {
            infobox.setOptions({ visible: false });
        }
    }


    var centerLocation;
    var accountName = "";
    var boxes = new Array();

      </script>
</head>
<body onload="GetMap();ClickGeocode();">
<table style="width:100%;" border="1">
<tr>
<td width="20%" style="vertical-align:top" >Radius (miles)
        <input type="text" id="milesText" size="2" value="10" />
        <input type="button" id="searchButton" value="Search" onclick="pinAccounts();"/><br />

</td>

<td >
<div id="mapDiv" style="height:450px;overflow:hidden;"></div>
</td>
</tr>
</table>

 

</body></html>

No comments:

Post a Comment