Saturday, 25 May 2013

Cross-Domain Ajax with CoffeeScript

Ajax! The workhorse technology, that underpins our Web 2.0 world. Normally is something that we take for granted as web developers.
Except when you're trying to develop something in a small group and it just won't behave!!

Ok, context: I was building the front end to a site and a colleague was working on the back. The big problem came when I was trying to get json data from his service.. on his machine. You get where this is going :p

Error jQueryXXXXXXXX was not called

Solution?!

Jsonp. (WTF!) 'Jsonp' stands for "JSON with padding". But in a nutshell 'Jsonp' is requesting your json data from a dynamically created element on the page.
 *I'm still lost!!*
In order to keep your data secure when visiting web sites. The elders of the Internet decided that cross domain scripting would be a bad idea. This means that your browser restricts javascript to only send/receiving data to the domain that the page is coming from.

The workaround(Hack) is to dynamically create a hidden element on the page that points to the domain that you want to get your information from. The request goes out and the respond as javascript. [Don't worry. If you are using jQuery 1.5(or higher) this is all handled for you by using the the 'jsonp' data type in the jQuery ajax request]

So there are two parts to this.
A Server bit and a Browser bit.
*The Server bit is important!!*

On the Browser we need to send the ajax and have a function to process the response.

opets = 
 type: 'GET'
 url: 'http://192.168.1.117/myService/get.json'
 dataType: 'jsonp'
 async: false
 crossDomain: true
 jsonpCallback: 'callMe'
 error: (jqXHR, textStatus, errorThrown) ->
  alert "AJAX Error: #{textStatus}"

$.ajax opets


window.callMe = (data) ->
 console.log data

Server side. When using JSONP you should set the content-type to javascript(insted on "json").. as the respoince will be wrapped in your callback function

if(isset($_GET['callback'])){
 header('Content-Type: application/javascript');
 echo $_GET['callback'].'('.$jsonData.')';
}