Working with Ajax, we have run into the Same Origin Policy over and over again. In this post, we’ll show you another way to get around it.
The Same Origin Policy restricts you from loading files from a server not your own. There is an exception: JavaScript (.js) files are allowed.
There are sites on the web where you can request information and have it passed back in JSONP format. The “P” stands for padding: JSONP is JSON with padding. The results are returned as a function call, with the results as parameters. That function can then be called in your program.
Let’s use this to get a stock quote from Yahoo. There are 3 parts to this: first, we have to make the request. Next, we handle the return. Finally, we execute the function.
1. Make the request
Dim YQI, URL, callback YQI = escape("select * from yahoo.finance.quotes where symbol in ('AAPL','GOOG','MSFT')") callback="requestComplete" URL = "http://query.yahooapis.com/v1/public/yql?q=" & YQI & _ "&format=json&env=http://datatables.org/alltables.env&callback=" & callback loadScript(URL)
Yahoo! has a very powerful API to look up all kinds of data. To make it easier, they have set up an interface using SQL like statements called YQI. In our code above, we start by creating our YQI request. The escape() function translates special characters and spaces so they can be sent in our Ajax call.
URL is then composed of our YQI request with the rest of the boilerplate that is needed. The most interesting part is the &callback part. It names the function that the return values will be wrapped in.
Having prepared everything, we can inject the script.
2. Inject the script
Yahoo! is going to return some code: it will be a call to the function we specified in callback, with the parameters all filled in. The following code will insert the code returned by Yahoo! into our program and execute it:
Function loadScript(URL) Dim head, script head=document.getElementsByTagName("head")[0] script=document.createElement("script") script.src=URL script.async=True head.appendChild(script) End Function
We do the usual checking to see if the call is complete. If it is, we will have gotten a text string back that looks something like this:
requestComplete({"query": {"count":3,"created":"2012-03-20T11:34:00Z","lang":"en-US","results": {"quote":...);
This is a valid function call, so when it is run, the function is executed.
3. Execute the function
The Eval() function causes requestComplete() to be called.
Function requestComplete(data) Dim quotes, i quotes=data.query.results.quote TextArea1.value="" For i=0 To Len(quotes)-1 TextArea1.value=TextArea1.value+quotes[i].symbol & _ ": " & quotes[i].Ask & vbCRLF Next End Function
The data that comes back is a fairly complex structure with a lot of data in it. You can copy it to the NotePad to see everything that is there. For now, we are just interested in the asking price of the stock. The results are returned in an array, with one element per stock.
Closing points
There are many web services that work in a similar fashion. One of the tip offs is if the calling string has an &callback argument. If it does, it probably can be used with this method.
Some of these services are free or limited, while others require an API key that you must obtain from the service.
Some places to go for services:
- Lots of stuff: Yahoo!
- Weather: Wunderground
- Elevation: Geonames
- Geographic Info: Geonames
Got more? Let us know at support@nsbasic.com.