The Shape of Everything
A website mostly about Mac stuff, written by August "Gus" Mueller
» Acorn
» Retrobatch
» Mastodon
» Micro.blog
» Instagram
» Github
» Maybe Pizza?
» Archives
» Feed
» Micro feed
March 28, 2009
(This post is from my old, old, super old site. My views have changed over the years, hopefully my writing has improved, and there is now more than a handful of folks reading my site. Enjoy.)

In my quest to convince you of how awesome JSTalk is/could be, let me tell you about "JSTalk Extras".

JSTalk Extras are loadable bundles of Objective-C code, which add functionality to your JavaScript programs via extra classes or functions. You make JSTalk Extras using the standard Cocoa bundle project, and place the resulting bundle in your ~/Library/Application Support/JSTalk/Extras/ folder.

So for instance, I thought it would be cool if you could talk to SQLite using my FMDB classes. So I put the classes in a bundle, and I'm now calling to SQLite from JavaScript:

%-var db = [FMDatabase databaseWithPath:"/tmp/jstalk.sqlite"];
[db open];
[db executeUpdate:"create table test (a text, b text, c integer, d double, e double)"];
[db beginTransaction];
var i = 0;
while (i++ < 20) {
    [db executeUpdate:"insert into test (a, b, c, d, e) values (?, ?, ?, ?, ?)" ,
    @"hi'", "Hello", i, [NSDate date], 2.2];
}
[db commit];

var rs = [db executeQuery:"select rowid,* from test where a = ?", "hi'"];

while ([rs next]) {
    print([rs stringForColumn:"rowid"] + " " + [rs stringForColumn:"a"] + " " +
    [rs stringForColumnIndex:2] + " " + [rs dateForColumn:"d"]);
}
[db close];-%

I think that's pretty awesome. And of course, you can download the code which adds this support to JSTalk from the repository.

If you include the JSTalk framework in your application, these bundles are loaded automatically. However, you can turn that feature off if you don't want 3rd party code running in your app space.

lil acorn

Of course, Cocoa comes with a ton of great classes as it is, so you may not need a JSTalk extra to do what you want. Here's an example for scraping the number of bundles MacHeist has currently sold:

%-var url = [NSURL URLWithString:"http://dynamic.macheist.com/sales-bundles.js"];
var s   = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:null];
var a   = [s componentsSeparatedByString:"["][1];
a       = [a componentsSeparatedByString:","][0];

print(a + " bundles sold");-%

I'm not sure why you'd care though.

Update: Actually, it occurred to me that since the URL I'm hitting is returning JavaScript... why not just eval it to get our result?

%-function updateBundles(countArray) {
    print(countArray[0] + " bundles sold");
}
var url = [NSURL URLWithString:"http://dynamic.macheist.com/sales-bundles.js"];
eval([NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:null] + "");-%

Update 2: And then it occurs to me that would be a really bad idea, since they could put in some nasty code. And look me here, executing it.