DownloadFor MacOSX 10.5out of date — Get it on Github |
Read upGoogle Code homepage |
Get the codeVia Git |
|
Write Cocoa apps in Javascript ! JSCocoa bridges Cocoa to JavascriptCore (WebKit's JS engine). It allows you to call C code, ObjC code, use C structs,
and build Javascript classes inheriting from ObjC classes. | |
| Follow JSCocoa updates on Twitter | |
| 2009 04 11 | Swizzle ! JSCocoa now lets you swizzle methods :
class NSButton
{
// Swizzle an instance method of an existing class
Swizzle- (void)drawRect:(NSRect)rect
{
// Draw something behind the button
...
// Call original swizzled method, this will call NSButton's drawRect:
this.Original(arguments)
// Draw something in front of the button
NSBezierPath.bezierPathWithOvalInRect(rect).stroke
}
}
swizzling is replacing a method's implementation with our own. This example swizzles Add Swizzle in front of a method definition to swizzle it. To call the original method, call |
| 2009 03 27 | Introducing JSTalk, an alternative to AppleScript. Gus Mueller has released the first version of JSTalk, a way to make your application scriptable in Javascript. It also supports an Objective-C syntax.
// JSTalk-enable your application
[JSTalk listen];
// From the JSTalk editor you can then script it in Javascript
var sketch = JSTalk.application("Sketch");
var doc = sketch.orderedDocuments()[0];
var rectangle = doc.makeNewBox();
rectangle.setWidth(100);
rectangle.setHeight(100);
// Or use an ObjC syntax
var bezierPath = [NSBezierPath bezierPath];
[bezierPath curveToPoint:pointA controlPoint1:pointB controlPoint2:pointC];
[bezierPath fill];
Get JSTalk from Github !
|
| 2009 03 10 | Use delegate methods to customize JSCocoa behaviour.
// Check if getting property is allowed - (BOOL) JSCocoa:(JSCocoaController*)controller canGetProperty:(NSString*)propertyName ofObject:(id)object inContext:(JSContextRef)ctx exception:(JSValueRef*)exception; // Custom handler for getting properties // Return a custom JSValueRef to bypass JSCocoa // Return NULL to let JSCocoa handle getProperty // Return JSValueMakeNull() to return a Javascript null - (JSValueRef) JSCocoa:(JSCocoaController*)controller getProperty:(NSString*)propertyName ofObject:(id)object inContext:(JSContextRef)ctx exception:(JSValueRef*)exception;These methods allow you to restrict access or customize behaviour. If you want to use JSCocoa as a plugin engine, implement canCallMethod to restrict method call, or canGetProperty and canSetProperty to restrict properties access. canGetGlobalProperty restricts access to ObjC classes, functions, structs and enums.
After restricting access with the
|
| 2009 02 18 | New class syntax inspired from Cappucino
// Define a new class
class MyClass < NSObject
{
// instance method
- (int)addX:(int)x andY:(int)y
{
return x + y
}
// class method
+ (float)addFloatX:(float)x andFloatY:(float)y
{
return x + y
}
// Interface Builder outlet
IBOutlet outlet1
// Interface Builder outlet using a Javacript notification
IBOutlet outlet2 (newValue)
{
log('new value of outlet2=' + newValue)
}
// Interface Builder action, using sender as default parameter
IBAction clickMe
{
log('Button clicked=' + sender)
}
// Interface Builder action, using custom parameter name
IBAction clickMeToo(notifier)
{
log('Button clicked=' + notifier)
}
}
There's some limitations on parameters (right now it's classes, structs, raw int/char/float) but these should go away in the future.
|
| 2009 02 18 | JSLocalizedString defers localization to Javascript functions. |
| 2009 02 13 | Using Pointers JSCocoa can now handle pointers and memory buffers.
// Functions like NSOpenGLGetVersion(int*, int*) expect two pointers to int
// JSCocoa detects pointer types and auto allocs required size
var major = new outArgument
var minor = new outArgument
NSOpenGLGetVersion(major, minor)
log('OpenGL version : ' + major + '.' + minor)
// Using with structures
var rect = new NSRect(10, 20, 30, 40)
var rect1 = new outArgument
var rect2 = new outArgument
NSDivideRect(rect, rect1, rect2, 5, NSMinXEdge)
log('Divided rect1=' + rect1)
// Using with ObjC methods : scanning a string with NSScanner
var scanner = NSScanner.scannerWithString('4.56 123')
var extractedFloat = new outArgument
scanner.scanFloat(extractedFloat)
log('extracted=' + extractedFloat)
//
// Memory buffers : manually allocating memory and using it as data source or sink
//
// Data source : copy color components into our buffer
// Allocate room for 4 floats
var buffer = new memoryBuffer('ffff')
// Extract components of a NSColor into our buffer
color.get({ red : new outArgument(buffer, 0),
green : new outArgument(buffer, 1),
blue : new outArgument(buffer, 2),
alpha : new outArgument(buffer, 3) })
log('Extracted red=' + buffer[0])
// Data sink : copy point coordinates into a NSBezierPath element
// Allocate room for 3 points
var buffer = new memoryBuffer('ffffff')
// Set new point values
buffer[0] = 10.0
buffer[1] = 5.0
...
...
// Fill a NSBezierPath element with our new coordinates
path.setAssociatedPoints_atIndex(buffer, 1)
Under the hood, JSCocoaOutArgument and JSCocoaMemoryBuffer handle all this.
|
| 2009 02 04 | Write Cocoa plugins in almost anything Want more than Javascript ? Grayson Hansard wrote PluginManager, a project that enables you to write Cocoa plugins in AppleScript, F-Script, Javascript, Lua, Nu, Python and Ruby. "PluginManager is a series of classes that provides support for a vast number of scripting languages as well as standard Cocoa bundles. It is designed based on AddressBook's applescript plugin support but can be used in a wide number of ways. If nothing else, this project should provide an example into calling of scripts that you can adapt to your own applications." |
| 2009 01 17 | iPhone libffi Here's a better way than prederivation : Tim Burks advocates a pool of reconfigurable handlers. These handlers can be shared about amongst classes : first, gather the method type encodings from the classes' methods then generate Javascript callbacks from them. Great strategy ! |
| 2009 01 16 | Elysium, a midi sequencer, uses JSCocoa for scripting. Check it out ! |
| 2009 01 15 | iPhone JSCocoa now compiles on the iPhone, thanks to the Nu language's libffi. It crashes because it can't create Javascript methods callable by ObjC. (mprotecting the closure for libffi fails). Looks like there are 3 possibilities :
|
| 2009 01 12 | Multiple interpreters support JSCocoa can now create multiple versions of itself, each independant — just like each page in Safari has its interpreter. A document application can host one instance of JSCocoa in each document, each having its own variables separate from the others. |
| 2009 01 10 | Gus Mueller on JSCocoa and Acorn Plugins in JavaScript |
| 2009 01 08 | JSCocoa moves to Github Fork, branch, push and pull away !
I love Git, it's really a "what's changed" manager for directories used as source control.
Files referenced once will exist only once, files moved will keep refering to the same object, and it's easy to use : |
| 2008 12 19 | Questions/Réponses sur JSCocoa [Developpez] |
| 2008 12 17 | JSCocoa Google Group Wanna talk about JSCocoa ? There's the place ! |
| 2008 12 17 | JSCocoa as a framework JSCocoa can now be added to an existing project as a framework — much simpler that before ! Checkout the latest version from svn. |
| 2008 12 11 | JSCocoa Garbage Collection |
| 2008 11 28 | JSCocoa Core Animation sample code |
| 2008 11 22 | JSCocoa interactive console for iPhone written by Kumagai Kentaro |
| 2008 10 24 | JSCocoa working on iPhone simulator — check it out via svn |
| 2008 10 15 | Advice ? on JSCocoa iPhone |
| 2008 10 15 | Updated documentation |
| 2008 10 14 | Questions/Réponses sur JSCocoa [Cocoa.fr] |
| 2008 10 10 | Command line interpreter and REPL for JSCocoa written by Tom Robinson |
| 2008 10 08 | Initial release |
| Everywhere dot | |
Just like in Ruby, call functions with or without parentheses. object.a().b().c() becomes object.a.b.c Alas, if (a.b.c) won't work — use if (a.b.c()) until toBoolean() arrives | |
| Cocoa | NSString* appName = [[[NSWorkspace sharedWorkspace] activeApplication] valueForKey:@"NSApplicationName"]; |
| JSCocoa | var appName = NSWorkspace.sharedWorkspace.activeApplication.NSApplicationName |
| Instance | |
Tired of the alloc/init dance ? Use instance to get an object allocated, inited, and retained by Javascript's Garbage Collector
| |
| Cocoa |
[[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 40)];
Need to [ release] when done |
| JSCocoa |
NSButton.alloc.initWithFrame(NSMakeRect(0, 0, 100, 40))
Need to release() when done NSButton.instance({ withFrame:NSMakeRect(0, 0, 100, 40) }) Handled by Javascript's GC |
| Get/Set | |
Instead of calling setVariable(newValue), use Javascript's setter syntax : object.variable = newValue
| |
| Cocoa |
NSString* title = [window title];
[window setTitle:@"Hello !"]; |
| JSCocoa |
var title = window.title
window.title = 'Hello !' |
| Call | |
| Use a jQuery-like syntax to call multiple parameter methods | |
| Cocoa | [obj callWithParam1:@"Hello" andParam2:"World"]; |
| JSCocoa |
obj.call({ withParam1:'Hello', andParam2:'World' })
obj['callWithParam1:andParam2:']('Hello', 'World') obj.callWithParam1_andParam2('Hello', 'World' ) |
| Fully Unicode | |
| Name your variables in your native language ! | |
| JSCocoa |
function 追加する(最初の, 次の) { return 最初の+ 次の } var 結果 = 追加する('こんにちは', '世界') NSApplication.sharedApplication.keyWindow.title = 結果 |
| Derive | |
| A hash will define classes in one go, but you can add methods anytime after | |
| Cocoa | In .h @interface MyButton : NSButton { IBOutlet NSButton* myOutlet; } - (IBAction)myAction:(id)sender; @end In .m @implementation MyButton - (IBAction)myAction:(id)sender { ... } @end |
| JSCocoa | defineClass('MyButton < NSButton', { myOutlet : 'IBOutlet' ,myAction : ['IBAction', function (sender) { ... }] }) |
| Shorthand Overload | |
A quick way to overload methods : define a new class, use NSClass[method] = fn to overload methods like drawRect: To call the parent method, one single syntax : this.Super(arguments) — no need to rewrite the method name !
| |
| JSCocoa | MyButtonClass['drawRect:'] = function(rect) { // super call this.Super(arguments) // Add some custom drawing ... } |
| Integrate in Interface Builder | |
| There's a catch here ! | |
|
|
JSCocoa works with NIBs, but you'll need to manually add IBOutlets and IBActions while creating your interface.
If you've ever wondered why there are + and - buttons in the Identity Inspector, wonder no more ! :)
|
| Check it out — it's open | |
| Wanna check in ? Mail me at parmanoir@gmail.com for write access. | |
Visit JSCocoa on Google Code, or check it out via Git : git clone git://github.com/parmanoir/jscocoa.git |