function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
JoannaJoanna 

Problem with Creating On Demand Apps book - Custom Yahoo Maps S-Control

Hi,

I'm new to Salesforce, so I was going through the Salesforce Creating On Demand Apps book.  Everything was working fine until I tried to implement the Yahoo Maps custom S-Control in chapter 10.  I copied and pasted the code from the downloaded Candidates Map file, so there are no typos on my part.  Then, I created my custom link (as instructed) and added it to the Position tab's page layout.  The custom link shows up on my Position details page fine.  However, when I click on it, the page simply blanks out.  The map doesn't show up. 

Is there anything else that I needed to do to get this to work?  Do I need to download any other tools or anything not mentioned in the Creating On Demand Apps book?

Any help is appreciated.

Thanks so much!
aezellaezell
I suspect the problem may be that the Yahoo API needs what they call an API key which is unique to your usage.

You can get an API key from Yahoo here: https://developer.yahoo.com/wsregapp/index.php

You'll need a Yahoo account of course.

There should be a spot in the Candidates Map code to put the API key. I think you can put it in place of YahooDemo in the URL in that code. I don't have the book in front of me to know for sure.

If that's not the issue, please show us the code as you pasted it in and maybe we can spot the issue.
JoannaJoanna
I now registered with yahoo and have an application id.  But, still the page comes up blank.  I tried simple code <html>hello world</html>, and it worked.  So, the S-Control and link are working properly.  It has to be something in the code block.  Here is what I am using:

I added my appid in.  (Previously the appid was salesforce.com)  Also, the book had 2 semi-colons in the style section "height: 475px;;".  I made that so that it was just 1.  Other than that, it has been simple copy/paste.

Thanks for any help.  I don't suppose there's any kind of debugging options within Salesforce for this?

<html>
<head>
<style type="text/css">
#mapContainer {
height: 475px;
width: 600px;
}
</style>

<script language="javascript" src="/soap/ajax/8.0/connection.js"
        type="text/javascript"></script>
<script type="text/javascript"
        src="http://api.maps.yahoo.com/ajaxymap?v=3.0&amp;appid=6hALp9_V34HJTZ.STO2.XbAAlySX3MrSr0upXdOcE6RxluC_wsQ3H3r4lfNV0bB4JrEko_M-">
        </script>

<script type="text/javascript">
var conn;
function initPage() {
   conn = sforce.connection;
   loadMap();
}

var reload = true;
var map;
var link;
var geoPoints = [];
var dataPointCount = 0;
var pointCounter = 0;

function geoCodeEnd(r) {
    if (r.success == 1) {
        if (r.GeoPoint.Lat != 0) {
            geoPoints[geoPoints.length] = r.GeoPoint;
            pointCounter++;
        }
    } else {
        pointCounter++;
    }
    if (pointCounter >= dataPointCount) {
        var bestZoomLevel = map.getZoomLevel(geoPoints);
        if (bestZoomLevel < 5) bestZoomLevel = 5;
        var geoCenter = map.getCenterGeoPoint(geoPoints);
        map.drawZoomAndCenter(geoCenter, bestZoomLevel);
        map.panToLatLon(geoCenter);
    }
}

function loadMap() {
    // Create a map object
    map = new YMap(document.getElementById('mapContainer'));
    // Display the map centered on given address
    YEvent.Capture(map, EventsList.onEndGeoCode, geoCodeEnd);
     map.addZoomLong();
    
    doQuery();
}

function doQuery() {
    if (reload == false) return;
    var positionId = "{!Position__c.Id}";
    var qr = conn.query("Select Candidate__c From Job_Application__c
                            Where Position__c = '" + positionId + "'");
    if (qr.size > 0) {
        var ids = [];
        var records = qr.getArray("records");
        for (var i=0;i<records.length;i++) {
            ids[i] = records[i].get("Candidate__c");
        }
        conn.retrieve("Id, Last_Name__c, First_Name__c, Street__c,
                       City__c, State_Province__c,
                       Current_Employer__c", "Candidate__c",
                      ids, plotMarkers);
    } else {
        // Display map of US if no Candidates found
        var myPoint = new YGeoPoint(40,-95);
        map.drawZoomAndCenter(myPoint, 14);
        alert("There are no candidates for this position to map.");
    }
    reload = false;
}

function doNav(arg) {
    window.parent.location = "/" + arg;
}

function plotMarkers(qr) {
    var records = qr;
    if (qr.getArray) {
        records = qr.getArray("records");
    }
    var counter = 1;
    if (records.length > 0) {
        for (var x=0;x<records.length;x++) {
            var db = records[x];
            if (db.get("Street__c") != null &amp;&amp;
                      db.get("City__c") != null &amp;&amp;
                      db.get("State_Province__c") != null ) {
                dataPointCount++;
                var addr = db.get("Street__c") + ", " +
                              db.get("City__c") + ", " +
                              db.get("State_Province__c");
                var marker = new YMarker(addr);
                marker.addLabel(counter);
                var name = db.get("First_Name__c") + " " +
                                  db.get("Last_Name__c") ;
                counter++;
                name = "<a href='" +
                       conn.describeSObject("Candidate__c").
                          urlDetail.replace("{ID}", db.get("Id"))
                       + "' target='_top'>" + name + "</a>";
                marker.personName = name;
                YEvent.Capture(marker, EventsList.MouseClick,
                    function() {this.openSmartWindow
                                   ("<div>This is where " +
                                     this.personName +
                                     " lives!<BR>&nbsp;</div>") });
                map.addOverlay(marker);
            }
        }
    }

}


</script>


</head>

<body onload="initPage();">
<div id="mapContainer"></div>

</body>
</html>
JoannaJoanna
I finally figured this one out.  I downloaded Eclipse SDK 3.2.2, along with the Apex Toolkit 8.1.0.  That way I was able to view this code in a decent editor.  The problem was 1) the yahoo application id 2) Copying the code in replaced "&" with "amp;" 3) the queries broken up by line breaks didn't work, so I moved them to 1 line each.  There were a few other problems that I cleaned up as well.

But, now the Yahoo! Maps interface works correctly.  Thanks for the help regarding the yahoo maps app id.
aezellaezell
Glad you got it working Joanna!

The & to &amp; thing I have faced in the past. It sometimes works either way, and sometimes only one way. It seems to depend on the server that the code is running from. In my tests on PHP, it seemed to make a difference with which version of CURL was installed and how it was installed. Obviously, the Salesforce platform is its own beast.
ARAR
Hi Joanna and aezell,

I'm also a Salesforce newbie. I ran into the same problem that you had with the Yahoo map. In my version of the Candidate Mapping Tool,  page came up blank, like you described.

I appreciated reading above what steps that you took to troubleshoot the problem and followed the same steps you suggested - tested with Hello World (works fine), got a Yahoo appID key (added it to the source), fixed the few things you found in error, viewed the source in Eclipse (it looked fine) - but the map is still not coming up.

The only thing I did not do was remove the line breaks in the lines that ended with ";". Below is the code.

Joanna, you mentioned "There were a few other problems that I cleaned up as well."  Could you list those as well?  Any other suggestions would be great.

Thanks!

Amy

<html>
<head>
<style type="text/css">
#mapContainer {
height: 475px;
width: 600px;
}
</style>


<script language="javascript" src="/soap/ajax/8.0/connection.js" type="text/javascript"></script>

<script type="text/javascript" src="http://api.maps.yahoo.com/ajaxymap?v=3.0&amp;appid=A6ho9gTV34Gc6WMT5nmb0rAl4WUqGeE5iGjawYzQZ0g1xBgsVb6pC3.H50PVZg--">
        </script>

<script type="text/javascript">

var conn;
function initPage() {
   conn = sforce.connection;
   loadMap();
}



var reload = true;
var map;
var link;
var geoPoints = [];
var dataPointCount = 0;
var pointCounter = 0;

function geoCodeEnd(r) {
    if (r.success == 1) {
        if (r.GeoPoint.Lat != 0) {
            geoPoints[geoPoints.length] = r.GeoPoint;
            pointCounter++;
        }
    } else {
        pointCounter++;
    }
    if (pointCounter >= dataPointCount) {
        var bestZoomLevel = map.getZoomLevel(geoPoints);
        if (bestZoomLevel < 5) bestZoomLevel = 5;
        var geoCenter = map.getCenterGeoPoint(geoPoints);
        map.drawZoomAndCenter(geoCenter, bestZoomLevel);
        map.panToLatLon(geoCenter);
    }
}

function loadMap() {
    // Create a map object
    map = new YMap(document.getElementById('mapContainer'));
    // Display the map centered on given address
    YEvent.Capture(map, EventsList.onEndGeoCode, geoCodeEnd);
     map.addZoomLong();

    doQuery();
}

function doQuery() {
    if (reload == false) return;
    var positionId = "{!Position__c.Id}";
    var qr = conn.query("Select Candidate__c From Job_Application__c
                            Where Position__c = '" + positionId + "'");

    if (qr.size > 0) {
        var ids = [];
        var records = qr.getArray("records");
        for (var i=0;i<records.length;i++) {
            ids[i] = records[i].get("Candidate__c");
        }
        conn.retrieve("Id, Last_Name__c, First_Name__c, Street__c,
                       City__c, State_Province__c,
                       Current_Employer__c", "Candidate__c",
                      ids, plotMarkers);
    } else {
        // Display map of US if no Candidates found
        var myPoint = new YGeoPoint(40,-95);
        map.drawZoomAndCenter(myPoint, 14);
        alert("There are no candidates for this position to map.");
    }
    reload = false;
}

function doNav(arg) {
    window.parent.location = "/" + arg;
}

function plotMarkers(qr) {
    var records = qr;
    if (qr.getArray) {
        records = qr.getArray("records");
    }

    var counter = 1;
    if (records.length > 0) {
        for (var x=0;x<records.length;x++) {
            var db = records[x];
            if (db.get("Street__c") != null &&;
                      db.get("City__c") != null &&;
                      db.get("State_Province__c") != null ) {
                dataPointCount++;
                var addr = db.get("Street__c") + ", " +
                              db.get("City__c") + ", " +
                              db.get("State_Province__c");
                var marker = new YMarker(addr);
                marker.addLabel(counter);
                var name = db.get("First_Name__c") + " " +
                                  db.get("Last_Name__c") ;
                counter++;
                name = "<a href='" +
                       conn.describeSObject("Candidate__c").
                          urlDetail.replace("{ID}", db.get("Id"))
                       + "' target='_top'>" + name + "</a>";
                marker.personName = name;
                YEvent.Capture(marker, EventsList.MouseClick,
                    function() {this.openSmartWindow
                                   ("<div>This is where " +
                                     this.personName +
                                     " lives!<BR>&nbsp;</div>") });
                map.addOverlay(marker);
            }
        }
    }

}
</script>
</head>

<body onload="initPage();">
<div id="mapContainer"></div>

</body>
</html>

JoannaJoanna
Sorry, I just saw your question.  Here is the final code that I wound up using.  Just replace your app id.
Hopefully, this will have pasted in correctly.

Joanna

<html>
<head>
<style type="text/css">
#mapContainer {
height: 475px;
width: 600px;
}
</style>

<script language="javascript" src="/soap/ajax/8.0/connection.js"
        type="text/javascript"></script>
<script type="text/javascript"
        src="http://api.maps.yahoo.com/ajaxymap?v=3.0&appid=PUTYOURAPPIDHERE">
        </script>

<script type="text/javascript">
var conn;
function initPage() {
   conn = sforce.connection;
   loadMap();
}

var reload = true;
var map;
var link;
var geoPoints = [];
var dataPointCount = 0;
var pointCounter = 0;

function geoCodeEnd(r) {
    if (r.success == 1) {
        if (r.GeoPoint.Lat != 0) {
            geoPoints[geoPoints.length] = r.GeoPoint;
            pointCounter++;
        }
    } else {
        pointCounter++;
    }
    if (pointCounter >= dataPointCount) {
        var bestZoomLevel = map.getZoomLevel(geoPoints);
        if (bestZoomLevel < 5) bestZoomLevel = 5;
        var geoCenter = map.getCenterGeoPoint(geoPoints);
        map.drawZoomAndCenter(geoCenter, bestZoomLevel);
        map.panToLatLon(geoCenter);
    }
}

function loadMap() {
    // Create a map object
    map = new YMap(document.getElementById('mapContainer'));
    // Display the map centered on given address
    YEvent.Capture(map, EventsList.onEndGeoCode, geoCodeEnd);
     map.addZoomLong();
    
    doQuery();
}

function doQuery() {
    if (reload == false) return;
    var positionId = "{!Position__c.Id}";
    var qr = conn.query("Select Candidate__c From Job_Application__c Where Position__c = '" + positionId + "'");
    if (qr.size > 0) {
        var ids = [];
        var records = qr.getArray("records");
        for (var i=0;i<records.length;i++) {
            ids[i] = records[i].get("Candidate__c");
        }
        conn.retrieve("Id, Last_Name__c, First_Name__c, Street__c, City__c, State_Province__c, Current_Employer__c", "Candidate__c", ids, plotMarkers);
    } else {
        // Display map of US if no Candidates found
        var myPoint = new YGeoPoint(40,-95);
        map.drawZoomAndCenter(myPoint, 14);
        alert("There are no candidates for this position to map.");
    }
    reload = false;
}

function doNav(arg) {
    window.parent.location = "/" + arg;
}

function plotMarkers(qr) {
    var records = qr;
    if (qr.getArray) {
        records = qr.getArray("records");
    }
    var counter = 1;
    if (records.length > 0) {
        for (var x=0;x<records.length;x++) {
            var db = records[x];
            if (db.get("Street__c") != null &&
                      db.get("City__c") != null &&
                      db.get("State_Province__c") != null ) {
                dataPointCount++;
                var addr = db.get("Street__c") + ", " +
                              db.get("City__c") + ", " +
                              db.get("State_Province__c");
                var marker = new YMarker(addr);
                marker.addLabel(counter);
                var name = db.get("First_Name__c") + " " +
                                  db.get("Last_Name__c") ;
                counter++;
                name = "<a href='" +
                       conn.describeSObject("Candidate__c").urlDetail.replace("{ID}", db.get("Id"))
                       + "' target='_top'>" + name + "</a>";
                marker.personName = name;
                YEvent.Capture(marker, EventsList.MouseClick,
                    function() {this.openSmartWindow
                                   ("<div>This is where " +
                                     this.personName +
                                     " lives!<BR>&nbsp;</div>") });
                map.addOverlay(marker);
            }
        }
    }

}


</script>


</head>

<body onload="initPage();">
<div id="mapContainer"></div>

</body>
</html>
ARAR
Thanks, Joanna!  I found the culprits. The conn.query and conn.retreive each do need to be on one line.

Also, and this is for others also doing this exercise, I didn't discover this until after the fact: unless you've added all the Candidate Object Custom Fields listed on page 86, this S-Control won't work. I only used the first four fields in the table, per the Note to save time. 

But, when the S-Control is run, at least the frame of the map, if not the map itself, would display (plus an error prompt because no candidate address was found).

A.