For the past week I’ve “found” JXA and have been exploring what is available in it. I’m trying to make a library for other scripters to automate an application (screenflow).
After a week of coding and a library with 10 functions I started to think “this is a huge mess and is super innefficient” e.g. To change the SMPTE setting I have:
function setSMPTE(value) {
var system = Application('System Events')
var ScreenFlow = system.processes['ScreenFlow']
preferencesOpen()
ScreenFlow.windows[0].toolbars[0].buttons['Timeline'].click()
ScreenFlow.menuBars[0].menus['ScreenFlow'].menuItems['Preferences…'].click()
//Get SMPTE element
var obj = ScreenFlow.windows[0].checkboxes["Use SMPTE timecode"]
//Set checkbox value
setCheckbox(obj,value)
//Close ScreenFlow preferences
ScreenFlow.windows[0].buttons[1].click()
}
Thing is, this isn’t the only preference I might want to change… I might have a whole list of preferences to change. And I probably want to save the original state to reload the initial state afterwards (because the user will likely want their preferences the same as they were…)
Ultimately I would need:
preferences.open()
state = preferences.getState()`
preferences.setState({SMPTE:1,...})
preferences.close()
//do other code
preferences.open()
preferences.setState(state)
preferences.close()
So initially I set out to make a class:
class preferences {
}
But I get an error - Error on line 1: SyntaxError: Unexpected use of reserved word 'class'
. A few iterations later I went even more basic:
function preferences(){
var object = {};
object.isOpen = false
object.open = function(){
this.isOpen = true
}
return object;
}
Great! Now I can call:
preferences = sf.preferences()
preferences.isOpen
And the script returns false, as expected! Sadly, when I try to call a method:
preferences = sf.preferences()
preferences.isOpen
preferences.open()
preferences.isOpen
I get the error - Error on line 3: TypeError: Object is not a function (evaluating 'preferences.open()')
After this I figured “Well maybe classes and objects weren’t implemented properly in JXA. Why don’t I use libraries! They seem to work fine!”
So now I made 2 libraries: “screenflow” and “properties” with the following code:
"screenflow": {
preferences = Library('preferences')
}
"preferences": {
this.isOpen = false
getOpen = function(){
return this.isOpen
}
setOpen = function(){
this.isOpen = true
}
}
And made the following 2 test scripts:
"test1": {
function notify(msg){
//Setup app for notifications.
var app = Application.currentApplication()
app.includeStandardAdditions = true
app.displayAlert(msg, {
soundName: 'Sosumi'
})
}
preferences = Library('preferences')
notify(preferences.isOpen.toString()) //Msgbox = false
preferences.setOpen()
notify(preferences.isOpen.toString()) //Msgbox = true
}
"test2": {
function notify(msg){
//Setup app for notifications.
var app = Application.currentApplication()
app.includeStandardAdditions = true
app.displayAlert(msg, {
soundName: 'Sosumi'
})
}
screenflow = Library('screenflow')
preferences = screenflow.preferences()
notify(preferences.isOpen.toString()) //Msgbox = false
preferences.setOpen() //Error on line 54: TypeError: Object is not a function (evaluating 'preferences.setOpen()')
notify(preferences.isOpen.toString())
}
After executing test1 I was getting very excited! It worked flawlessly and I assumed this meant everything was prepared for the next test where I include a library in another library! But alas, I was apparently a fool to think so. You can’t access Sub-Library methods from Libraries. But you can access Sub-Library properties from Libraries.
Is this generally the case? Or is there a way to do sub-classes that I haven’t tried yet?
EDIT: Fixed some errors in copying