Note: this applies to v2 only.
Table of Contents
- Introduction
- Reproducing the problem
- A quick fix
- A more permanent and transparent fix
- Conclusion
- Related Articles
Introduction
Hi
Remember, some of us had a bug with Google's Geo API and JSONP? Well the main reason (according to me) is that they don't want you to use the service directly nor using it with a third party library. They want you to use it via their JavaScript API. But sometimes people must call the service in a RESTful way (With jQuery plugins for example). Talking about the popular jQuery, the "bug" is especially present in this library:
Reproducing the problem
Here's the scenario to reproduce the bug (click on the button, you should receive a status code 610):
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js" type="text/javascript"></script> <script type="text/javascript"> // <![CDATA[ $('#buttonTest1').click(function () { $.ajax({ params: { q: 'montreal', output: 'json', v: 2, sensor: false, key: 'ABQIAAAAzAkrOIsv60fbtV-5UlnnJxRUrcFJRfPs1DYZSl5DdA7w5qtvARRv6HblVCIt_AgTSnG3PdPypHTBEQ' }, url: 'http://maps.google.com/maps/geo', dataType: 'jsonp', cache: false, success: function (data) { alert('Status code: ' + data.Status.code); } }); }); // ]]> </script>
What's wrong? Clicking on the button will produce this request: http://maps.google.com/maps/geo?callback=jQuery15102910673765909235_1300669342297&q=montreal&output=json&v=2&sensor=false&key=ABQIAAAAzAkrOIsv60fbtV-5UlnnJxRUrcFJRfPs1DYZSl5DdA7w5qtvARRv6HblVCIt_AgTSnG3PdPypHTBEQ&_=1300669368614
A quick fix
Now I'll show you a fix. Let's see if you're able to spot the difference (again, click on the button):
<script type="text/javascript"> // <![CDATA[ $('#buttonTest2').click(function () { $.ajax({ url: 'http://maps.google.com/maps/geo?q=montreal&output=json&v=2&sensor=false&key=ABQIAAAAzAkrOIsv60fbtV-5UlnnJxRUrcFJRfPs1DYZSl5DdA7w5qtvARRv6HblVCIt_AgTSnG3PdPypHTBEQ', dataType: 'jsonp', cache: false, success: function (data) { alert('Status code: ' + data.Status.code); } }); }); // ]]> </script>
Again, this will produce the following request: http://maps.google.com/maps/geo?q=montreal&output=json&v=2&sensor=false&key=ABQIAAAAzAkrOIsv60fbtV-5UlnnJxRUrcFJRfPs1DYZSl5DdA7w5qtvARRv6HblVCIt_AgTSnG3PdPypHTBEQ&callback=jQuery15108036324891551678_1300669681039&_=1300669709521
The main difference is that the callback parameter is almost at the end of the query. It seems that the callback parameter must be after some other key parameters?
So you have a fix. You must serialize yourself the parameters at the end of the url. jQuery will then append its own parameters after yours. It seems to do the trick. But thats not handy: sometimes plugins are only accepting URLs to do their queries (they let jQuery handle the parameters). So your stuck again :(
A more permanent and transparent fix
If you want a more transparent fix, I hacked the jQuery 1.5.1 library. Just replace what's in bold here (in the minified version):
[...]a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange[...]
With this JavaScript snippet (sorry for the mess):
[...]a.scriptCharset),d.src=/*fix*/a.url.match(/\?callback=[a-zA-Z0-9_-]+&/) == null ? a.url : a.url.replace(a.url.match(/\?callback=[a-zA-Z0-9_-]+&/), '?') + '&' + a.url.match(/\?callback=[a-zA-Z0-9_-]+&/)[0].substring(1, a.url.match(/\?callback=[a-zA-Z0-9_-]+&/)[0].length - 1)/*fix*/,d.onload=d.onreadystatechange[...]
What is does? Just before sending any ajax request, the callback parameter will be pushed at the end of the URL (if there's a callback parameter). You can then use jQuery as usual with the Geocoding Maps API in a more transparent way.
Conclusion
You must realize that you must read the terms and the agreements of the Google Maps API libraries prior to using it. My blog post was for demonstration purposes only!
I'm putting time and effort on this blog and having you here is my reward. Make me feel better and better everyday by spreading the love with the buttons below! Also, don't hesitate to leave a comment. Thanks for reading!
Related Articles
- Create Zoomable Images Using The Google Maps API
- Beginning with jQuery - A Solid Foundation to Learn The Basics
- Google Maps API and jQuery - Tips to Avoid Using Both
- StackOverflow DevDays - (Talk 4 of 6) - jQuery
- Google Maps API and jQuery - Memory Leaks Revisited
- Google Street View And Google Maps Interaction - Sample Showcase
- JSONP and Google Maps API Geocoder - Not a Bug
See ya
3 comments:
What's interesting about this is that v3 seems to work fine with json and jsonp, with jquery, for the geocodes. I am getting an HTTP 200 code from the Fiddler HTTP Proxy; however, I am still not able to do anything with the JSON/JSONP data in the "success" portion. I see that the Google GeoCode API returned the JSON/JSONP object successfully; status=OK and I can visually see the object iself from the Fiddler Proxy. So, I know it works. But why on Earth won't my code allow me to process the JSON/JSONP data? I believe I understand the concept of cross-domain ajax, same site policy, but if that were the case, that json is not working because of cross-domain access, then why would my HTTP Proxy return an HTTP code 200 and Status OK with the complete JSON/JSONP object? I mean, I can visually inspect every bit of data in the object from within the HTTP Proxy, just not in my code. I am using FireFox 4, in this case, as well.
Here is how I am calling it:
$.getJSON("http://maps.googleapis.com/maps/api/geocode/json", { address: "90210", sensor: false }, function(data) {
alert("JSON Data: " + data);
});
I would appreciate any help. Thank you.
Hi Mike,
Need help problem Google map json response
var url='http://maps.googleapis.com/maps/api/geocode/json?latlng=13.049082,80.233496&output=json&v=2&sensor=false&key=ABQIAAAAAFtdHQuUtN66POQgIG9AghQVWYqFFJ5lOubwFLAo8VUMXJKaZhTNUYtH9p1k3JD5X5eUWXGKkWrylg';
$('#button').click(function ()
{
$.ajax({
url: url,
dataType: 'jsonp',
cache: false,
success: function (data)
{
alert('Status: ' + data);
}
});
});
Hi Mike,
I am unable to display all the results requested from the Google Places Api..i used pagenation and getting 60 results but only can display 20..and 40 using settimeoutfuntion()...getting the following error: Uncaught TypeError: Cannot read property 'length' of null
Any clue?
Post a Comment