+ Start a Discussion
JNicJNic 

Passing a JS multidimensional array as a string from an APEX query

Hey guys,

 

I'm integrating google maps using their JS API V3, and I've got it working except for one stupid little thing...

 

Basically, I wanted to perform queries through APEX (to minimize client resource usage) then pass those results back to the PAGE for googleMap JS API processing.

 

 

When the user input search parameters, and clicks a command link, the link calls an action function which initiates the query by passing the parameters back to the controller. The controller initiaites the query, and processes the results.

 

Here is where I get stuck!

 

How do I pass those results back as a JS friendly multidimensional array?

 

I've made an ugly controller that takes the list and constructs a string in the form of a JS array.

 

(assume I've done my query, and populated public address__c [] addresses = new address__c[0];

 

	public string  getFormattedAddresses() {
		for (integer i = 0;i < addresses.size(); i++ ) {
			address__c a = addresses.get(i);
			//Construct a friendly string...
			// name = 1
			// lat = 2
			// long = 3
			// streetAddress = 4
			
			if (formattedAddresses != null) {
				formattedAddresses = formattedAddresses + ', [\''
				+ a.id + '\', \'' 				//0 string
				+ a.name + '\', ' 				//1 string
				+ a.lat__c + ', '				//2 int
				+ a.long__c + ', \''			//3 int
				+ a.streetAddress__c + '\']';   //4 string
			} 
			else {
				formattedAddresses = '[\'' 
				+ a.id + '\', \'' 				//0 string
				+ a.name + '\', ' 				//1 string
				+ a.lat__c + ', '				//2 int
				+ a.long__c + ', \''			//3 int
				+ a.streetAddress__c + '\']';   //4 string
			}
		}
		return formattedAddresses;
	}

 

 

Then, on the VF page, once the query has been completed, the actionstatus performs the googleMap initialize function, and passes that string value (which I've rendered in the page as an inputHidden) into the function:

 

                <!-- Call the initialize function when done and pass the results. -->
                <apex:actionStatus id="mapStatus" 
                    startText="    Going..." 
                    stopText="     Done!" 
                    onstop="initialize(document.getElementById('{!$Component.formattedAddresses}').value)"/>

 

 

my Initialize function looks like this:

 

        <script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3.2&sensor=false&callback=initialize">
        </script>

    <script type="text/javascript" >
        var markers = new Array();

        function initialize(formattedAddresses) {
            alert('Initialize() was called!');
            <!--Here is the initial lat/long... In the future, this should be centered on the users actual point if avail through blackberry I should also add a marker here one time-->
            var myLatlng = new google.maps.LatLng(49.286711, -123.113815);
            var myOptions = {
                zoom: 12,
                center: myLatlng,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            }
            var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
            <!-- my maps bounds so we can dynamically fit them to the view -->
            var bounds = new google.maps.LatLngBounds();

            <!-- This is the JS list of addresses... This is passed right from the googleMapController after being formatted to be JS friendly -->
            var addresses = [
               formattedAddresses
            ];

            <!-- How many addresses do I have? -->
            alert('Number of addresses: ' + addresses.length + '= ' + addresses);
            
            <!-- The info window instance we will use to populate data -->
            //var info = new google.maps.InfoWindow();

            <!-- Loop through the addresses and add them as markers -->
            for(var i = 0; i < addresses.length; i++) {
                <!-- My specific address -->
                var addressToMark = addresses[i];
                <!--  Now pull out the specific addresses columns to make a latlng NOTE we should never change these columns! -->
                var latLng = new google.maps.LatLng(addressToMark[2], addressToMark[3]); 
                
                <!-- Now create a marker in the array -->
                markers[i] = new google.maps.Marker({
                    position: latLng,
                    map: map,
                    title: addressToMark[1]
                });
                
                <!--  Now fit the bounds to include this marker -->
                bounds.extend(latLng);
                map.fitBounds(bounds);

                <!-- Now call an external function to create infowindow for that marker... -->
                attachInfo(markers[i], i);
            }
            <!-- end for loop -->
            
            <!-- Attach infoWindow to a specified marker -->
            function attachInfo(marker, number) {
                var addressToInfo = addresses[number];
                    var infoHtml = '<a href="/' + addressToInfo[0] + '">' + addressToInfo[1]; + '</a>' + 
                    '<p>' + addressToInfo[4] + '</p>'
                    var infowindow = new google.maps.InfoWindow({ 
                        content: infoHtml
                    });
                google.maps.event.addListener(marker, 'click', function() {
                    infowindow.open(map,marker);
                });
            }
            <!-- end attachInfo -->
        }
        <!-- End initialize -->

 

When it gets to the alert to prove that I have addresses in my array, it looks like this:

 

 

Number of addresses: 1= ['a07A0000006Rv78IAC', 'ADD-0000002', 49.2867114, -123.113815, '250 Howe st'], ['a07A0000006Rv6yIAC', 'ADD-0000001', 49.2766039, -123.1173663, '950 cambie street'], ['a07A0000006RuzmIAC', 'ADD-0000000', 49.213630, -122.961624, '6860 Rumble st'], ['a07A0000006S3CbIAK', 'ADD-0000006', 49.1681134, -122.5905083, '9124 Gay st']

 

Which is of course wrong... it should say 4 addresses, not 1.

 

 

If i manually paste that alert into my initialize function like so:

 

            <!-- This is the JS list of addresses... This is passed right from the googleMapController after being formatted to be JS friendly -->
            var addresses = [
               
['a07A0000006Rv78IAC', 'ADD-0000002', 49.2867114, -123.113815, '250 Howe st'], ['a07A0000006Rv6yIAC', 'ADD-0000001', 49.2766039, -123.1173663, '950 cambie street'], ['a07A0000006RuzmIAC', 'ADD-0000000', 49.213630, -122.961624, '6860 Rumble st'], ['a07A0000006S3CbIAK', 'ADD-0000006', 49.1681134, -122.5905083, '9124 Gay st']
            ];

 It works fine!!!

 

Number of addresses: 4= a07A0000006Rv78IAC,ADD-0000002,49.2867114,-123.113815,250 Howe st,a07A0000006Rv6yIAC,ADD-0000001,49.2766039,-123.1173663,950 cambie street,a07A0000006RuzmIAC,ADD-0000000,49.21363,-122.961624,6860 Rumble st,a07A0000006S3CbIAK,ADD-0000006,49.1681134,-122.5905083,9124 Gay st

 

 

 

 

 

So where am I going wrong with my string/array?

 

Thanks!

JNicJNic

I should also say, that if there is abetter way to construct that js array, I'm open to that... My way is tedious...

 If fact, is there a way to pass an apex list directly to the initialize function, then parse it in theere?

Jeremy_nJeremy_n

You may want to check out this CodeShare project: Force.com for Google Maps and Earth . The code you're looking for is probably in there, if not the entire component you're trying to create.

 

Jeremy