views:

26

answers:

2

Hi all,

I'm trying to query the OpenCalais service semanticproxy.com. Unfortunately, their url format is as follows:

http://service.semanticproxy.com/processurl/APIKEY/jsonp:handler_function/http://en.wikipedia.org/wiki/Germany

notice that the function callback, is not in a callback=? parameter, but rather follows the response format (jsonp:). This means that I can't use .getJSON, but rather need to use the .ajax method. So I have the following object definition:

function Subject() {
}

Subject.prototype.populate = function(page_title) {
  var url = "http://service.semanticproxy.com/processurl/APIKEY/jsonp:handler/http://en.wikipedia.org/wiki/" + page_title;
  $.ajax({url: url, dataType: "script", type: "GET", cache: false, callback: null, data: null});
};

var handler = function (data) {
  // do stuff with the returned JSON
};

s = new Subject();
s.populate("Germany");

This works fine. But what I really want to do is set properties of my Subject object. But I don't know how to create a function in the context of the Subject that will be able to be used as the callback. i.e:

Subject.prototype.handler = function(data) { this.title = data.title } 

Any ideas?

A: 

I don't think you're going to be able to do this, just because of how JSONP works, look at how it actually comes back to the browser, it pretty much does this:

<script type="text/javascript">
  handler({ title: "Germany", ...other properties... });
</script>

There's no way to maintain a reference here, you could do one request at a time, or keep an object map for each subject, but there's no way to do it in the JSONP request.

An object map would look something like this:

//delcare this once for the page
var subjects = {};

//do this per subject
var s = new Subject();
s.populate("Germany");
subjects["Germany"] = s;

Then in your hanldler, if any of the data properties is "Germany", you could get it that way, for example:

var handler = function (data) {
  var subject = subjects[data.title];
  //subject is  your Germany subject, use it, go nuts!
};
Nick Craver
Thanks Nick. Glad I'm learning the cans and cant's before I try to architect something more than test scripts. Thanks again.
kmc
A: 

You'd have to set a function on the window object. This is essentially (I think) what jQuery does with its .getJSON method. The below is a bit hacky but hopefully it points you in the right direction:

function Subject() {
}

Subject.prototype.populate = function(page_title) {
    // Save context object
    var subject = this;
    // Create function name like subjectHandler1281092055198
    var functionName = "subjectHandler" + new Date().getTime();
    window[functionName] = function(data) {
        // Invoke function with saved context and parameter
        subject.handler.call(subject, data);
    }
    var url = "http://service.semanticproxy.com/processurl/APIKEY/jsonp:" + functionName + "/http://en.wikipedia.org/wiki/" + page_title;
    $.ajax({url: url, dataType: "script", type: "GET", cache: false, callback: null, data: null});
};

Subject.prototype.handler = function (data) {
  // do stuff with the returned JSON
};

s = new Subject();
s.populate("Germany");
roryf
Re-read the question carefully, I read it exactly as you did the first time...his callback works, he wants to know how to reference the `Subject` that called the populate method.
Nick Craver
@Nick re-read the solution carefully, it does exactly that.
roryf
Thanks roryf. I think this is giving me *a* Subject, but as Nick said, not *the* Subject. With the insight you've given I took another look at the jQuery source (blew my mind the first time), and it seems that that is what is going on. So even with a normal "callback=?" you never get *the* Subject. Thanks for that.
kmc
It executes the `handler` function on the original `Subject` instance, using the correct context so inside that function you have access to all the objects properties using `this`. Isn't that what you wanted?
roryf
In fact it does, sorry roryf. I tested it but had made an error in my test code. Probably time for bed. Cheers for that!
kmc