Just coming back to using JSCocoa after some time and, of course, all knowledge has evaporated.
I'm looking to provide some jQuery style functions for scripting my app which I want to be globally available. Taking a look at the jQuery source code I notice they are using 'window' as a global context for the browser session.
Is there an equivalent global context object in JSCocoa to which I can attach functions such as '$' ?
Just use 'this' in the global scope. In a webpage's global scope,
'this' and 'window' are two different names for the global object
(alert(this==window) will return true)
JSCocoa has no default name for the global object, you can create one
yourself :
var globalObject = this
function attachStuffToGlobalObject()
{
globalObject.$ = function () { ... }
}
// Add stuff
attachStuffToGlobalObject()
// Call added stuff
$(....)
> Just coming back to using JSCocoa after some time and, of course, all
> knowledge has evaporated.
> I'm looking to provide some jQuery style functions for scripting my
> app which I want to be globally available. Taking a look at the jQuery
> source code I notice they are using 'window' as a global context for
> the browser session.
> Is there an equivalent global context object in JSCocoa to which I can
> attach functions such as '$' ?
On Thu, Oct 1, 2009 at 12:03 AM, Patrick Geiller <parman...@gmail.com> wrote: > Just use 'this' in the global scope. In a webpage's global scope, 'this' and > 'window' are two different names for the global object (alert(this==window) > will return true)
Ah, sweet. Thanks Patrick.
Are you aware of any components/frameworks for syntax aware JS editing that I could embed?
I'm also interested in what kind of debugging support might be available, any thoughts about that?
On Thu, Oct 1, 2009 at 12:03 AM, Patrick Geiller <parman...@gmail.com> wrote: > Just use 'this' in the global scope. In a webpage's global scope, 'this' and > 'window' are two different names for the global object (alert(this==window) > will return true)
I've just realised this isn't quite what i want. In a browser each window provides it's own global context. In my app I have one JSCocoa sharedController instance but that is creating a global context over a range of "documents".
This means that my $ function can't make inferences about where to look for certain things.
It occurs to me that I might be able to do this by creating a scope for each document within which the $ function is defined related to that scope. I guess I would then need to use bind to call my Javascript callback function in the context of the appropriate scope object.
Looking at my use of callJSFunction it's not clear to me how I'd use bind to set the scope of the function call.
Does what I'm saying (even broadly) make sense? And, if so, do you have any advice about how I can implement this?
Not sure if this is really applicable to your scenario, but for my
Spice plugin for Espresso, I use a Javascript wrapper to load in
individual plugin files that makes handling scope a lot easier. Basically, the Objective-C code loads up my bootstrapping function
using callJSFunctionNamed:withArguments: and passes specific data
about the current context via the arguments. The bootstrapping
function then configures standard global variables, loads the plugin
file into a generic function to keep it in its own scope, and then
executes the main function of the plugin file (if there is one). You
could presumably do something similar, using the bootstrapping
function to configure the specific scope variables that need to be
available to your plugins. The whole process was inspired by Narwhal
and its Server.js modular approach to handling Javascript, and the
benefit would be that you could then use things like binding and so
forth a lot easier than trying to do it straight from Objective-C.
For reference, here's the specific line where I'm loading in the
plugin file to a generic function (SpiceController is a globally
available object I setup with JSCocoa so I could make use of file I/O
and so forth):
The rest of the bootstrapping file is probably too specific to my
project to be much use to you, but hopefully that'll give you some
idea of what the heck I'm talking about. :-)
Good luck! I'd be interested to hear if you come up with an
alternative for handling scope in JSCocoa-loaded Javascript plugins.
> On Thu, Oct 1, 2009 at 12:03 AM, Patrick Geiller
> <parman...@gmail.com> wrote:
>> Just use 'this' in the global scope. In a webpage's global scope,
>> 'this' and
>> 'window' are two different names for the global object (alert >> (this==window)
>> will return true)
> I've just realised this isn't quite what i want. In a browser each
> window provides it's own global context. In my app I have one JSCocoa
> sharedController instance but that is creating a global context over a
> range of "documents".
> This means that my $ function can't make inferences about where to
> look for certain things.
> It occurs to me that I might be able to do this by creating a scope
> for each document within which the $ function is defined related to
> that scope. I guess I would then need to use bind to call my
> Javascript callback function in the context of the appropriate scope
> object.
> Looking at my use of callJSFunction it's not clear to me how I'd use
> bind to set the scope of the function call.
> Does what I'm saying (even broadly) make sense? And, if so, do you
> have any advice about how I can implement this?
On Thu, Oct 1, 2009 at 1:32 AM, Ian Beck <georgethef...@gmail.com> wrote: > Not sure if this is really applicable to your scenario, but for my > Spice plugin for Espresso, I use a Javascript wrapper to load in > individual plugin files that makes handling scope a lot easier. > Basically, the Objective-C code loads up my bootstrapping function > using callJSFunctionNamed:withArguments: and passes specific data > about the current context via the arguments. The bootstrapping > function then configures standard global variables, loads the plugin > file into a generic function to keep it in its own scope, and then > executes the main function of the plugin file (if there is one). You
I've been thinking it over and I'm concerned that my app is also multi-document and there is threading involved.
I can't remember now whether JSCocoa supports access from multiple threads. I recall when I was using MacRuby I had to switch all my callbacks to the main thread due to crash issues there... not sure if I switched things back.
It occurs to me that the safest approach might be to use a separate JSCocoa instance for each document which will also solve the scope issue.
Alternatively I could rip out multi-document which hasn't turned out to be very useful in this app.
Thanks for the suggestions. I have some puzzling to do :)
* Regarding the scope from multiple instances : do you need to worry about that ? Why not create your '$' function in each one of your documents ?
* Threading : JSCocoa isn't thread safe. I don't think it'd crash, but you might get errors of undefined objects. I need to fix this.
* Sharing js stuff between multiple contexts : starting from Safari 4, there is the concept of concept groups which I think I must use (use JSGlobalContextCreateInGroup for each dependant context, in your case each document context). But then I don't remember what data you need to share data across contexts ? Maybe Ian's method would be the simplest ? Have one context, with each document having its own scope.
On Thu, Oct 1, 2009 at 1:25 PM, Patrick Geiller <parman...@gmail.com> wrote: > * Regarding the scope from multiple instances : do you need to worry > about that ? Why not create your '$' function in each one of your > documents ?
Thanks for clarifying these issues Patrick.
But in order for the function to be globally available it needs to be attached to the global object, no? If I put it in the document then I will have to reference it via a document instance which is certainly possible but less succinct. Or am I missing something?
I confess my JS knowledge is rather pedestrian.
> * Threading : JSCocoa isn't thread safe. I don't think it'd crash, but > you might get errors of undefined objects. I need to fix this.
Okay. I suspect I probably didn't go back to multi-threading since I've not had any crashes. However I've not made much use of it either because it hasn't turned out to be as convenient as I'd hoped.
That's largely because any errors in the script aren't easily managed from within the app.
> * Sharing js stuff between multiple contexts : starting from Safari 4, > there is the concept of concept groups which I think I must use (use > JSGlobalContextCreateInGroup for each dependant context, in your case > each document context). But then I don't remember what data you need > to share data across contexts ? Maybe Ian's method would be the > simplest ? Have one context, with each document having its own scope.
Actually it's the reverse I don't want to share anything between documents, I want - essentially - the browser case of each document being entirely independent.
I'm actually thinking about dumping multiple documents altogether. When I started building Elysium I made it multi-document because my previous two apps I hadn't and I ended up regretting it and having to retrofit it.
But multi-document has never, in practice, made much sense in Elysium. It might considerably simplify things to get rid of it. But it would be quite a wrench code wise.
I want to take a look at Gus' code this evening and try and steal his editor (at the moment I use a plain text view). I'd also like to have some smarter error trapping and debugging facility. Not sure what's possible there.
Still I now actually need this in earnest so it's time to knuckle down and figure it all out.
> But in order for the function to be globally available it needs to be > attached to the global object, no? If I put it in the document then I > will have to reference it via a document instance which is certainly > possible but less succinct. Or am I missing something?
I meant if you give document its own JSCocoa instance, you can just load the same '$' function in each. (Just call evalJSFile('$.js') on each)
> Okay. I suspect I probably didn't go back to multi-threading since > I've not had any crashes. However I've not made much use of it either > because it hasn't turned out to be as convenient as I'd hoped.
> That's largely because any errors in the script aren't easily managed > from within the app.
Yes, handling script errors can be a pain, all the more if it's multithreaded. And right now, don't use multithreading in JSCocoa.
> Actually it's the reverse I don't want to share anything between > documents, I want - essentially - the browser case of each document > being entirely independent.
OK, then no problem. Just use a different JSCocoa instance for each document. This way you don't have to worry about sharing stuff, each one is independant and has its own global object and data.
> But multi-document has never, in practice, made much sense in Elysium. > It might considerably simplify things to get rid of it. But it would > be quite a wrench code wise.
Be careful to not regret it again ! Given that you're building a music synthesizer, having two documents open - like a tutorial document and the document you're working on - can be very useful. You should keep documents around.
> I want to take a look at Gus' code this evening and try and steal his > editor (at the moment I use a plain text view). I'd also like to have > some smarter error trapping and debugging facility. Not sure what's > possible there.