31.01.2011

Advanced Google Maps Integration

Dieses Beispiel zeigt, wie sich Google Maps in das Kontakt, Firmen- und Lead-Formular integrieren lässt um die Route vom Benutzer zum Kunden anzuzeigen.

Umgebung:
Microsoft Dynamics CRM 2011 RC
(vanilla/Out-Of-The-Box)

Deployment:
onpremise

Achtung:
In CRM Online funktioniert das ganze leider nicht. Das Problem ist, den Internet Explorer dazu zubringen, einen iFrame mit HTTP-Content in einer Webseite mit HTTPS-Content anzuzeigen. Google Maps ist leider nicht über HTTPS verfügbar.


Grundlagen:

Anforderungen:
  • auf den Formularen von Firma, Kontakt und Lead soll jeweils eine neue Bereich "Navigation Map" eingeblendet werden
  • in diesem neuen Formularbereich soll ein iFrame mit Google Maps angezeigt werden
  • es wird automatische die Route vom aktuellen Benutzer zum Kunden angezeigt
  • sollte beim aktuellen Benutzer keine Adresse hinterlegt sein, wird die Adresse der BU herangezogen
  • sollte auch hier keine Adresse gefunden werden, wird die Kundenadresse als Standord angezeigt
  • die Karte auf dem Formular wir eingebettet dargestellt
  • am Formular-Ribbon soll ein Button "Map" angefügt werden
  • dieser öffnet die jeweilige Route bzw. den Standort in einem neuen Fenster mit "Google-Map-Controls"

#1: Lösung erstellen und Entitäten hinzufügen
Der neuen Lösung "Google Maps Navigation" werden die Entitäten Account, Contact und Lead hinzugefügt.

#2: Icons hinzufügen
Der Lösung werden zwei Icons als Web Resource hinzugefügt.

GoogleMapsNavigationIcon16.png





GoogleMapsNavigationIcon32.png






#3: JavaScript-Bibliothek hinzufügen
Der Lösung wird die Datei "navmaplib.js" als Web Resource mit folgendem Inhalt hinzugefügt:

var fromAddress;
var isEmbedded = true;

function formLoad() {   
    retrieveCrmObject("SystemUser", Xrm.Page.context.getUserId());
   
}

function retrieveCrmObject(entityName, entityId)
{
    // Build REST Endpoint
    var url = Xrm.Page.context.getServerUrl()
            + "/xrmservices/2011/organizationdata.svc/"
            + entityName + "Set(guid'" + entityId + "')";

    // Create CRM Request
    var request = new XMLHttpRequest();
    request.open("GET", url, true);
    request.setRequestHeader("Accept", "application/json");
    request.setRequestHeader("Content-Type",
                             "application/json; charset=utf-8");
    request.onreadystatechange = function () {
        if (request.readyState == 4) {
            if (request.status == 200) {
                var crmObject = eval('(' + request.responseText + ')').d;
                fromAddressRetrieved(crmObject);
            }
        }
    }

    // Send Crm Request
    request.send();
}

function fromAddressRetrieved(crmObject) {
    fromAddress = "";
    if (typeof (crmObject.SystemUserId) != "undefined") {
        if (crmObject.Address1_Line1 != null) {
            fromAddress = crmObject.Address1_Line1;
            fromAddress += addAddressItem(crmObject.Address1_PostalCode);
            fromAddress += addAddressItem(crmObject.Address1_City);
            fromAddress += addAddressItem(crmObject.Address1_Country);
           
            loadMap();
        }

       
        if (fromAddress == "") {
            retrieveCrmObject("BusinessUnit", crmObject.BusinessUnitId.Id);
        }       
    }
    else {
        if (crmObject.Address1_Line1 != null) {
            fromAddress = crmObject.Address1_Line1;
            fromAddress += addAddressItem(crmObject.Address1_PostalCode);
            fromAddress += addAddressItem(crmObject.Address1_City);
            fromAddress += addAddressItem(crmObject.Address1_Country);                    }
    }
    loadMap();
}

function addAddressItem(crmAttribute)
{
    if(crmAttribute != null)
        return "," + crmAttribute;
    else return "";
}

function loadMap() {
    var url = getUrl();
    var embedded = "";
    if(isEmbedded)
        embedded = "&output=embed";
    if (url != "") {
        // Set iFrame source to google maps url
        Xrm.Page.ui.controls.get("IFRAME_navigationmap").setSrc(url + embedded);
    }
    else {
        Xrm.Page.ui.controls.get("IFRAME_navigationmap").setSrc("about:blank");
    }
}

function getUrl() {
    // Get address data from form
    var toAddress = "";
    if (Xrm.Page.getAttribute("address1_line1").getValue() != null) {
        toAddress = Xrm.Page.getAttribute("address1_line1").getValue();
        toAddress += addAddressItem(Xrm.Page.getAttribute("address1_postalcode").getValue());
        toAddress += addAddressItem(Xrm.Page.getAttribute("address1_city").getValue());
        toAddress += addAddressItem(Xrm.Page.getAttribute("address1_country").getValue());
    }
   
    // Build google maps url   
    var url = "";
    if (toAddress != "") {
        if (fromAddress == "") {
            url = "http://maps.google.de/maps?q=" + toAddress;
        }
        else {
            url = "http://maps.google.de/maps?q=from: " + fromAddress + " to:" + toAddress;
        }
    }

    return url;
}

function openMap() {
    var url = getUrl();
    if(url != "") {
         window.open(url, "mywindow", "width=800,height=600,resizable=Yes");
    }
    else
    {
        alert("No Addresses found.");
    }
   
}
 
#4: JavaScript-Bibliothek im Formular registrieren
In den Formularen von Firma, Kontakt und Lead ist die JavaScript-Bibliothek sowie die Funktion "buttonClick" im "OnLoad"-Ereignis zu registrieren.

4.1 JavaScript-Bibliothek und -Funktion im Formular registrieren


#5: Button-XML (RibbonDiffXml) in die Lösung einfügen
Dieses Arbeitspaket wurde detailliert in der Post "Simple Form-Button w/ JavaScript-Function" beschrieben.
Folgende Änderungen werden zusätzlich gemacht:
  • der neue XML-Knoten wird jeweils einmal in den Entities account, contact und lead hinterlegt
  • die Namender Web Resourcen werden angepasst
  • der FunctionName wird auf "openMap" gesetzt
--
:: Links / Weiterführende Information: