I'm trying to access the properties of an object in an app called Papers3 using JXA. I'm new to JXA and this is proving challenging, especially because of the lack of documentation.
Here is a shot of the dictionary for the object I'm trying to look at
I'm trying to get the IDs for the currently displayed windows in the app.
My attempt at this is:
var Papers = Application('Papers');
Papers.includeStandardAdditions = true
Papers.libraryWindow.displayedPublications()
Running it throws an error and the output is:
Error on line 4: TypeError: Papers.libraryWindow.displayedPublications is not a function. (In 'Papers.libraryWindow.displayedPublications()', 'Papers.libraryWindow.displayedPublications' is undefined)
Error -2700: Script error.
Also, if I call just Papers.libraryWindow
The result is:
[function anonymous] {
"name":"",
"prototype":{"constructor":[function anonymous]}
}
I'm not sure what to do.
Well, JXA is broken obfuscated moribund junk and AS not much better off either, but the key thing to understand here is that Apple event IPC is not OOP, it is RPC + simple first-class relational queries. Despite the syntactic sugar, its closest relative is actually SQL database programming, not browser DOM manipulation, so once you get your head around that it’ll [hopefully] start to make a bit more sense.
An “AppleScriptable” application presents its data as a heavily abstracted relational graph—an “Apple Event Object Model”—where each node is related to other nodes by one-to-one and/or one-to-many relationships. There’s no such thing as “classes” or “objects” in the OO sense; it’s just the jargon that got attached for documentation purposes. Thus what an application’s dictionary calls a “property” is either a simple attribute containing a primitive value (number, string, list, etc; e.g. the name property of a Finder file) or a one-to-one relationship (e.g. the current track property of iTunes’ application), and what it calls “elements” is a one-to-many relationship (in your case, the libraryWindows elements of Papers’ application object).
For example, Papers.libraryWindows.displayedPublications.get() should return a list of the displayed publications of every library window in Papers (though whether that actually works in practice depends on how well implemented an app’s AEOM is, not to mention JXA’s own implementation issues); or you can use various reference forms (by-index, by-name, etc; though several are broken/unsupported in JXA) to narrow your query to, say, just the first library window, e.g. Papers.libraryWindows[0].displayedPublications.get().
You might get some insight from browsing the NodeAutomation documentation, which includes a rough overview of AEOM and how to assemble queries which you then send to it via commands (remote procedure calls) to resolve and process as it sees fit. JXA syntax isn’t as pretty, and various operations that work perfectly in AS barf in JXA, but it’ll give you a rough idea.
That said, I strongly recommend sticking to AppleScript. The language is a mess, but at least it has some documentation and user community to help you find your way around it (even if they don’t deeply understand it either).
It's a little detail, I think. libraryWindow needs to be plural and it's necessary to specify which one. You can use several forms:
Index form eg. libraryWindows[0]
ByName eg. libraryWindows.byName('Papers')
So, to access the first library window, you use: libraryWindows[0].
Try this:
(() => {
'use strict'
const app = Application('Papers');
const oWin = app.libraryWindows[0]
return oWin.displayedPublications()
})();
For Papers 3 specific JXA examples, see:
mac-scripting - Automation scripts for macOS
For more general info, see:
JXA Resources
Related
After sweating blood and tears I've finally managed to set up a Node C++ addon and shove a web-platform standard MediaStream object into one of its C++ methods for good. For compatibility across different V8 and Node.js versions, I'm using Native Abstractions for Node.js (nan):
addon.cc
NAN_METHOD(SetStream)
{
Nan::HandleScope scope;
v8::Local<v8::Object> mediaStream = info[0]->ToObject();
}
addon.js
setStream(new MediaStream());
For what it's worth, this works correctly (i.e. it does not obliterate the renderer process on sight), and I can verify the presence of the MediaStream object, e.g. by returning its constructor name from the C++ method:
addon.cc
info.GetReturnValue().Set(mediaStream->GetConstructorName());
When called from JavaScript through setStream, this would return the string MediaStream, so the object is definitely there. I can also return the mediaStream object itself and everything will work correctly, so it's indeed the object I need.
So, how would I read audio data (i.e. audio samples) from this MediaStream object in C++? As a sidenote, the actual data read (and processing) would be done in a separate std::thread.
Bounty Update
I understand this would be sort of easier/possible if I were compiling Electron and/or Chromium myself, but I'd rather not get involved in that maintenance hell.
I was wondering if it would be possible without doing that, and as far as my research goes, I'm convinced I need 2 things to get this done:
The relevant header files, for which I believe blink public should be adequate
A chromium/blink library file (?), to resolve external symbols, similarly to the node.dylib file
Also, as I said, I believe I could compile chromium/blink myself and then I would have this lib file, but that would be a maintenance hell with Electron. With this in mind, I believe this question ultimately comes down to a C++ linking question. Is there any other approach to do what I'm looking for?
Edit
ScriptProcessorNode is not an option in my case, as its performance makes it nearly unusable in production. This would require to process audio samples on the ui/main thread, which is absolutely insane.
Edit 2
AudioWorklets have been available in Electron for some time now, which, unlike the ScriptProcessorNode (or worse, the AnalyzerNode), is low-latency and very reliable for true C++ backed audio processing even in real time.
If someone wants to go ahead and write an AudioWorklet-based answer, I'll gladly accept, but beware: it's a very advanced field and a very deep rabbit hole, with countless obstacles to get through even before a very simple, general-purpose pass-through prototype (especially so because currently in Electron, Atomics-synced, buffered cross-thread audio processing is required to pull this off because https://github.com/electron/electron/issues/22503 -- although getting a native C++ addon into one audio renderer thread, let alone multiple threads at the same time, is probably equally as challenging).
The MediaStream header is part of Blink's renderer modules, and it's not obvious to me how you could retrieve this from nan plugin.
So, instead let's look at what you do have, namely a v8::Object. I believe that v8::Object exposes all the functionality you need, it has:
GetPropertyNames()
Get(context, index)
Set(context, key, value)
Has(context, key)
Unless you really need a strictly defined interface, why not avoid the issue altogether and just use the dynamic type that you already have?
For getting audio data out specifically, you would need to call getAudioTracks() on the v8::Object, which probably looks something like this?
Note: I don't think you need a context, v8 seems to be happy with it being empty: v8/src/api/api.cc
Should look something like this, plus some massaging of types in and out of v8.
v8::MaybeLocal<v8::Value> get_audio_tracks = mediaStream->Get("getAudioTracks");
// Maybe needs to be v8::Object or array?
if (!get_audio_tracks.IsEmpty()) {
v8::Local<v8::Value> audio_tracks = get_audio_tracks.ToLocalChecked()();
}
In Ember.js, we use Ember's own object variants which recommend/necessitate using this.get and this.set in order to access object attributes.
I (mostly) understand why this is done, and appreciate the consistency and flexibility it adds to the Ember programming experience, but I do feel that I lose out on my IDE's sanity checking.
With Jetbrain products (or any good IDE w/ deep analysis and completion) I can usually rely on symbol suggestions to make sure I'm choosing the correct variable name. Entering in strings with ember relies on me to get the name right, and I'm a fallible human.
I have a few thoughts regarding possible solutions.
Some IDE plugin which does static analysis to suggest the correct string to use
An ES6 or alternative transpired language which accesses members the ember way by default
Some way of automatically establishing string constants where I need them
Some ember debugging setting which at least throws warnings if I try to get a variable which hasn't been defined.
I would also find it useful to throw warnings if ember catches me trying to set an attribute to undefined.
Hopefully, someone will tell me that one of these solutions exists, something better has been thought of, or my problem isn't really a problem.
(An example to illustrate my problem:)
In the following snippet
const email = this.get('email');
const newInvitation = this.store.createRecord('invitation', {email: email});
I am trying to get the attribute email but the real attribute I meant to get was called emailAddress. When I create the record, I do so with an undefined email field which isn't caught until later in the code.
It wasn't terrible to debug, but if I have to manually sift through every line of code every time I misspell something, I'm going to waste a lot of time and be a sad debugging-boy. Help!
Currently we don't have a good solution for this. However the future looks bright!
Currently there is a lot of work going on in the ember-typings repository to build a typescript definition that will allow the typescript language server to give you that completion. This will give you completions for things like this.get('foo') but not for things like this.get('foo.bar') in near future.
Also I've build this, which will allow you to omit .get and .set on browsers that support the proxy object. However this is more a proof-of-concept then something you should use in production!
If you just want debug messages if you access a property thats null you can use unknownProperty:
unknownProperty(key) {
console.log('access to unknown property');
}
However I sometimes its required to access an unknown property for code like this:
if(!obj.get('foo')) {
obj.set('foo', 'bar');
}
So overall I would recommend you to try out typescript, because thats probably the solution that will give you a good developer experience soon and good support from the community as well. Interesting is also the ES classes RFC, that shows, that ember goes toward standard ES classes and at some point we won't .set and .get at all.
Also glimmer integration is going forward, and inside a glimmer component you won't need .set and .get.
Also I don't recommend you ember script. I tried it out, but there is basically no-one using it, and no support at all.
This question is regarding a best practice for structuring data objects using JS Modules on the server for consumption by another module.
We have many modules for a web application, like login view, form handlers, that contain disparate fragments of data, like user state, application state, etc. which we need to be send to an analytics suite that requires a specific object format. Where should we map the data? (Pick things we want to send, rename keys, delete unwanted values.)
In each module. E.g.: Login knows about analytics and its formatting
requirements.
In an analytics module. Now analytics has to know
about each and every module's source format.
In separate [module]-analytics modules. Then we'll have dozen of files which don't have much context to debug and understand.
My team is split on what is the right design. I'm curious if there is some authoritative voice on the subject that can help us settle this.
Thanks in advance!
For example,
var objectForAnalytics = {
logged_in: user.get('isLoggedIn'),
app_context: application.get('environment')
};
analytics.send(objectForAnalytics);
This short sample script uses functions from 3 modules. Where should it exist in a well-organized app?
JS doesn't do marshaling, in the traditional sense.
Since the language encourages duck typing and runs all loaded modules in a single VM, each module can simply pass the data and let a consumer choose the fields that interest them.
Marshaling has two primary purposes, historically:
Delivering another module the data that it expects, since C-style structures and objects do not support extra data (usually).
Transferring data between two languages or modules built on two compilers, which may be using different memory layouts, calling conventions, or ABIs.
JavaScript solves the second problem using JSON, but the first is inherently solved with dictionary-style objects. Passing an object with 1000 keys is just as fast as an object with 2, so you can (and often are encouraged) to simply give the consumer what you have and allow them to decide what they need.
This is further reinforced in languages like Typescript, where the contract on a parameter type is simply a minimum set of requires. TS allows you to pass an object that exceeds those requires (by having other fields), instead only verifying that you are aware of what the consumer states they require in their contract and have met that.
When you do need to transform an object, perhaps because two library use the same data with different keys, creating a new object with shallow references is pretty easy:
let foo = {
bar: old.baz,
baz: old.bin
};
This does not change or copy the underlying data, so any changes to the original (or the copy) will propagate to the other. This does not include primitive values, which are immutable and so will not propagate.
I've recently started using Backbone.js. I like the architecture, in terms of features it's almost exactly what I need...
... However I found the following caveats:
For Collections get means something different than for Models. There is no set. Attributes should be accessed in a regular way. I find it rather inconsistent. It's easy to confuse models and collections sometimes. Is there anything that can be done to overcome this?
Assigning initial values inside Model.extend doesn't always work. For example assigning url will not override the default behaviour. This can only be achieved through a call to set() method. Again very error prone.
I still don't know whether it's required to use get/set inside initialize() call.
I don't understand why I can't just call _.bindAll(this) inside initialize() and I have to list specific function names to be bound like this: _.bindAll(this, firstFunc, secondFunc, ...). This is not very DRY.
I would like to know: what are the best practices regarding the mentioned situations? What do you do to make the framework more consistent - any monkey patching? Am I doing anything wrong / against the convention?
I'd be grateful for any good real world examples. I did find this: http://documentcloud.github.com/backbone/docs/todos.html and http://liquidmedia.ca/blog/2011/01/backbone-js-part-1/ and those don't address any of the mentioned problems. In fact they just present the simplest ideas and absolutely no border cases, so anything more complicated could be useful.
EDIT:
Ok, and there is one more fundamental think I don't understand:
Am I ever allowed to place additional attributes on extension like this: var SomeModel = Backbone.Model.extend({ myattribute: myvalue }) ?
If so, then why don't subsequent calls to new SomeModel().get("myattribute") work ?
What exactly is this inside initialize() ? Is it model class or model instance ?
EDIT(2):
Well, I found this: http://maccman.github.com/spine/. It looks like Backbone.js 2.0, shares a similar name too :). Haven't tested it yet, which might be a bit of a show stopper, as the library is very recent. However from the docs side of things it looks very promissing. It gets rid of most of the problems that I found, it simplifies the API, it even gets rid of the dependency on underscore.js which for a library is a good thing. I'll post my further findings here.
Ok, I think I can say it quite confidently now: Backbone is dead, long live Spine.
Spine isn't exactly a fork of Backbone. It is however very similar and clearly inspired by some of the design decisions. It could be said that the author tried to retain as much as it was possible the original backbone API, getting rid of everything unnecessary or illogical. I find it also easier to extend. The list of changes includes among other things:
Getting rid of the dreaded Collections. "class methods" are used instead,
Getting most out of js prototypical nature (i.e. no get/set is needed). Attributes are accessed directly. An explicit call to save() is required in order to trigger an event.
Views and Controllers are now merged into new type of Controllers together whose purpose is to respond to DOM events and bind to model events.
The name :)
I find those design decisions coherent and sensible.
The reason there is no 'set' for Collections is because Collections are not arrays, they are sets, which are potentially ordered. The only supported way to place an element at a particular position is to add it to the collection and then sort the collection.
I've started to wrap my functions inside of Objects, e.g.:
var Search = {
carSearch: function(color) {
},
peopleSearch: function(name) {
},
...
}
This helps a lot with readability, but I continue to have issues with reusabilty. To be more specific, the difficulty is in two areas:
Receiving parameters. A lot of times I will have a search screen with multiple input fields and a button that calls the javascript search function. I have to either put a bunch of code in the onclick of the button to retrieve and then martial the values from the input fields into the function call, or I have to hardcode the HTML input field names/IDs so that I can subsequently retrieve them with Javascript. The solution I've settled on for this is to pass the field names/IDs into the function, which it then uses to retrieve the values from the input fields. This is simple but really seems improper.
Returning values. The effect of most Javascript calls tends to be one in which some visual on the screen changes directly, or as a result of another action performed in the call. Reusability is toast when I put these screen-altering effects at the end of a function. For example, after a search is completed I need to display the results on the screen.
How do others handle these issues? Putting my thinking cap on leads me to believe that I need to have an page-specific layer of Javascript between each use in my application and the generic methods I create which are to be used application-wide. Using the previous example, I would have a search button whose onclick calls a myPageSpecificSearchFunction, in which the search field IDs/names are hardcoded, which marshals the parameters and calls the generic search function. The generic function would return data/objects/variables only, and would not directly read from or make any changes to the DOM. The page-specific search function would then receive this data back and alter the DOM appropriately.
Am I on the right path or is there a better pattern to handle the reuse of Javascript objects/methods?
Basic Pattern
In terms of your basic pattern, can I suggest modifying your structure to use the module pattern and named functions:
var Search = (function(){
var pubs = {};
pubs.carSearch = carSearch;
function carSearch(color) {
}
pubs.peopleSearch = peopleSearch;
function peopleSearch(name) {
}
return pubs;
})();
Yes, that looks more complicated, but that's partially because there's no helper function involved. Note that now, every function has a name (your previous functions were anonymous; the properties they were bound to had names, but the functions didn't, which has implications in terms of the display of the call stack in debuggers and such). Using the module pattern also gives you the ability to have completely private functions that only the functions within your Search object can access. (Just declare the functions within the big anonymous function and don't add them to pubs.) More on my rationale for that (with advantages and disadvantages, and why you can't combine the function declaration and property assignment) here.
Retrieving Parameters
One of the functions I really, really like from Prototype is the Form#serialize function, which walks through the form elements and builds a plain object with a property for each field based on the field's name. (Prototype's current – 1.6.1 – implementation has an issue where it doesn't preserve the order of the fields, but it's surprising how rarely that's a problem.) It sounds like you would be well-served by such a thing and they're not hard to build; then your business logic is dealing with objects with properties named according to what they're related to, and has no knowledge of the actual form itself.
Returning Values / Mixing UI and Logic
I tend to think of applications as objects and the connections and interactions between them. So I tend to create:
Objects representing the business model and such, irrespective of interface (although, of course, the business model is almost certainly partially driven by the interface). Those objects are defined in one place, but used both client- and server-side (yes, I use JavaScript server-side), and designed with serialization (via JSON, in my case) in mind so I can send them back and forth easily.
Objects server-side that know how to use those to update the underlying store (since I tend to work on projects with an underlying store), and
Objects client-side that know how to use that information to render to the UI.
(I know, hardly original!) I try to keep the store and rendering objects generic so they mostly work by looking at the public properties of the business objects (which is pretty much all of the properties; I don't use the patterns like Crockford's that let you really hide data, I find them too expensive). Pragmatism means sometimes the store or rendering objects just have to know what they're dealing with, specifically, but I do try to keep things generic where I can.
I started out using the module pattern, but then started doing everything in jQuery plugins. The plugins allow to pass page specific options.
Using jQuery would also let you rethink the way you identify your search terms and find their values. You might consider adding a class to every input, and use that class to avoid specifically naming each input.
Javascript is ridiculously flexible which means that your design is especially important as you can do things in many different ways. This is what probably makes Javascript feel less like lending itself to re-usability.
There are a few different notations for declaring your objects (functions/classes) and then namespacing them. It's important to understand these differences. As mentioned in a comment on here 'namespacing is a breeze' - and is a good place to start.
I wouldn't be able to go far enough in this reply and would only be paraphrasing, so I recommend buying these books:
Pro JavaScript Design Patterns
Pro Javascript techniques