Using JXA for file editing?

Adobe Community Professional ,
Mar 16, 2021 Mar 16, 2021

Copy link to clipboard

Copied

I'm still trying to understand JXA and getting nowwhere fast because my limited JavaScript knowledge. Here is a script I edited from another site. I'd like to understand how to do simple things like create an object, in this case an ellipse. What am I missing?


I get this error on line 61 (newEllipse = doc.layer[0].Ellipse({…)
Error: requested property not available for this object (1262)

 

const aiApp = Application('Adobe Illustrator')
aiApp.includeStandardAdditions = true
const doc = aiApp.documents[0]
aiApp.activate()
newEllipse = doc.layer[0].Ellipse({
    left: 100,
    top: -100,
    width: 400,
    height: 200,
    reversed: false,
    inscribed: true
})
newEllipse.make()

 

TOPICS
Scripting

Views

322

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 16, 2021 Mar 16, 2021

Copy link to clipboard

Copied

I'm not sure if you have to have a lowercase 'ellipse', maybe so, but otherwise you have doc.layer[0], but it should be doc.layers[0].

 

And you will need to declare your variables with 'var' the first time cause otherwise they can be stuck in global memory where it may create a scenario of something working only some of the time.

 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 16, 2021 Mar 16, 2021

Copy link to clipboard

Copied

Thanks @Silly-V . Same result with this (upper or lowercase "e"):

const aiApp = Application('Adobe Illustrator')
aiApp.includeStandardAdditions = true
const doc = aiApp.documents[0]
aiApp.activate()
newEllipse = doc.layers[0].ellipse({
left: 100,
top: -100,
width: 400,
height: 200,
reversed: false,
inscribed: true
})
newEllipse.make()

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Mar 16, 2021 Mar 16, 2021

Copy link to clipboard

Copied

Please excuse the elementary question:  How are you running this code in Illustrator, because most of it is not valid ExtendScript/JavaScript ES3?  This will create an ellipse.

 

var doc = app.documents[0];
doc.layers[0].pathItems.ellipse(100, -100, 400, 200, false, true);

 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 16, 2021 Mar 16, 2021

Copy link to clipboard

Copied

Yea , it is this https://developer.apple.com/library/archive/releasenotes/InterapplicationCommunication/RN-JavaScript...

 

Actually as far as @rcraighead I wanna know - are you are standing in the middle of the orchard of plenty as all the same JSX javascript for Illustrator should work just the same inside of JXA? Maybe with some minor and annoyingly undocumented yet very vital and mind-breaking changes just once in a while? But try it out and see if hopefully most of the scripts on here are directly usable without much fuss.

Maybe JXA is like applescript commands but written in javascript that's a little different style than extendscript. So it technically should let you do a lot of the same stuff plus cool things that only AppleScript can do!

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 16, 2021 Mar 16, 2021

Copy link to clipboard

Copied

So far my experience is that my JSX functions do  not work when called from a JXA script. I'm still trying to learn the basics of JXA. Most the examples seem to be for communicating with Apple applications. My goal is to freely share data between Chrome, Keyboard Maestro, Illustrator and Photoshop without funneling the variables through Keyboard Maestro. Since I've spent the last 3 years learning JavaScript I'm not particularly interested in starting over with AppleScript, which I understand has this capability.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 16, 2021 Mar 16, 2021

Copy link to clipboard

Copied

Hi @femkeblanco . I am attempting to understand JXA. I'm running the JXA script directly from VSCode using the "AppleScript" extention.

Right now my workflow is to call a JSX function from Keyboard Maestro by way of a "do JavaScript" AppleScript. I'd like to learn to access variables directly from Chrome and push them to Illustrator without first saving them as Keyboard Maestro variables. But JXA is a high hurdle for me.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Mar 17, 2021 Mar 17, 2021

Copy link to clipboard

Copied

Sorry. I misread JXA as JSX in the title.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 16, 2021 Mar 16, 2021

Copy link to clipboard

Copied

Yes, the pathItems thing was very important too, I forgot about that part doh!

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Most Valuable Participant ,
Mar 16, 2021 Mar 16, 2021

Copy link to clipboard

Copied

One shot into darkness:

Could Applescript be using right and bottom instead of width and height???

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 17, 2021 Mar 17, 2021

Copy link to clipboard

Copied

@pixxxelschubser , This is actually a JXA script. The odd thing is the "Applescript" VSCode extension is needed to run it. I'm just trying to make sense of it all.

rcraighead_0-1615984777577.png

I DID successfully get the properties of an existing ellipse with this script:

const aiApp = Application('Adobe Illustrator')
aiApp.includeStandardAdditions = true
const doc = aiApp.documents[0]
aiApp.activate()
theProp = doc.layers[0].pageItems[0].properties()

Result here. It referres to "Position" instead of left, top. But I haven't learned how to set it yet.

closed:true, area:29843.861752567256, length:612.3963486672205, guides:false, filled:true, fillColor:'tCMi'{ 'CYAN':0, 'MAGN':0, 'YELL':0, 'BLAK':0 }, fillOverprint:false, stroked:true, strokeColor:'tCMi'{ 'CYAN':0, 'MAGN':0, 'YELL':0, 'BLAK':100 }, strokeOverprint:false, strokeWidth:1, strokeDashes:, strokeDashOffset:0, strokeCap:butted, strokeJoin:mitered, strokeMiterLimit:10, clipping:false, evenodd:false, resolution:800, entirePath:'tSEG'{ 'pAnc':[ 389.35, -190.102 ], 'caIN':[ 389.35, -136.281 ], 'caOT':[ 389.35, -243.923 ], 'caCR':'e056' }, 'tSEG'{ 'pAnc':[ 291.898, -287.554 ], 'caIN':[ 345.719, -287.554 ], 'caOT':[ 238.077, -287.554 ], 'caCR':'e056' }, 'tSEG'{ 'pAnc':[ 194.446, -190.102 ], 'caIN':[ 194.446, -243.923 ], 'caOT':[ 194.446, -136.281 ], 'caCR':'e056' }, 'tSEG'{ 'pAnc':[ 291.898, -92.6497 ], 'caIN':[ 238.077, -92.6497 ], 'caOT':[ 345.719, -92.6497 ], 'caCR':'e056' }, selectedPathPoints:Application("Adobe Illustrator CC 2015").documents.at(0).layers.at(0).pathItems.at(0).pathPoints.at(0), Application("Adobe Illustrator CC 2015").documents.at(0).layers.at(0).pathItems.at(0).pathPoints.at(1), Application("Adobe Illustrator CC 2015").documents.at(0).layers.at(0).pathItems.at(0).pathPoints.at(2), Application("Adobe Illustrator CC 2015").documents.at(0).layers.at(0).pathItems.at(0).pathPoints.at(3), polarity:positive, url:, note:, layer:Application("Adobe Illustrator CC 2015").documents.at(0).layers.at(0), locked:false, hidden:false, selected:true, position:194.44585987261235, -92.64968152866277, width:194.9044585987249, height:194.9044585987249, geometricBounds:194.44585987261235, -92.64968152866277, 389.35031847133723, -287.55414012738765, visibleBounds:193.94585987261235, -92.14968152866277, 389.85031847133723, -288.05414012738765, controlBounds:193.94585987261235, -92.14968152866277, 389.85031847133723, -288.05414012738765, name:, blendMode:normal, opacity:100, isolated:false, knockout:disabled, editable:true, sliced:false, visibilityVariable:null, pixelAligned:false, wrapped:false, wrapOffset:null, wrapInside:null, container:Application("Adobe Illustrator CC 2015").documents.at(0).layers.at(0), bestType:specifier, defaultType:specifier, class:pathItem, index:1
 
I can set "width" and "height" of a target object like this:
theProp = doc.layers[0].pageItems[0].height = 100
 
I think I need to use a different syntax (JSON?) to set the position.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Most Valuable Participant ,
Mar 17, 2021 Mar 17, 2021

Copy link to clipboard

Copied

Sorry, that was just an assumption on my part.

(I am not familiar with Applescript / JXA.)

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 17, 2021 Mar 17, 2021

Copy link to clipboard

Copied

I think you are on the right track though because it is referred to as "Position" in the properties.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Mar 18, 2021 Mar 18, 2021

Copy link to clipboard

Copied

Honestly, you’re wasting your time trying to use JXA (Apple’s “JavaScript for Automation”). It has never worked properly and is long abandoned by Apple. (JXA failed so hard, Apple killed off its entire Mac Automation department.) It works up to a point, albeit confusingly, whereupon something breaks and there’s nothing you can do about it. For instance, its support for “class” and “constant” types is all screwed up, and it’s impossible to specify “beginning”/“end”/“before”/“after” when making new elements or moving/duplicating existing ones. It also tends to break more often on older apps that predate Mac OS X, such as Adobe CS and Microsoft Office, due to the greater variation and unique quirks in how those apps’ “AppleScript” interfaces are designed.

 

If you want to use JavaScript, use JSX (Adobe’s “ExtendScript”). It’s ancient ES3 and not without its own bugs (e.g. the notorious “out of space” PARM/MRAP error), but at least those bugs are understood and can be worked around (e.g. don’t define any global names and wrap all your code in an anonymous function call). You can write JSX code in any plain text/code editor, although if you want integrated debugger support you’ll have to use Microsoft’s VSCode with Adobe’s JSX plugin. If you need to control multiple Adobe apps, use JSX + Bridge (see Adobe’s BridgeTalk class documentation). And Adobe still actively support JavaScript and will hopefully start rolling out modern UXP for AI and ID in the next couple years; JSX is just dead product walking.

 

Otherwise, stick to AppleScript for Mac desktop automation. It’s a crappy, moribund language, but at least speaks Apple events correctly and has semi-decent documentation and community support.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Mar 26, 2021 Mar 26, 2021

Copy link to clipboard

Copied

function run() {
  const aiApp = Application('Adobe Illustrator') ;
  const doc = aiApp.documents[0] ;
  
  const newEllipse = aiApp.make({
    new: 'ellipse', 
    at: doc.layers[0], 
    withProperties: {
      bounds: [100, -100, 500, 100], // [left, top, right, bottom]
      reversed: false, 
	  inscribed: true
    }
  }) ;
}

/* in AppleScript...
on run
	tell application "Adobe Illustrator"
		tell document 1
			set newEllipse to make new ellipse at layer 1 with properties {bounds:{100, -100, 500, 200}, reversed:false, inscribed:true}
		end tell
	end tell
end run
*/

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Mar 26, 2021 Mar 26, 2021

Copy link to clipboard

Copied

That lets you create a new object. However, JXA can’t tell AI where in the stacking order to insert it.

 

AppleScript:

tell application "Adobe Illustrator"
	tell document 1
		set theEllipse to make new ellipse with properties {bounds:{100, 100, 500, 500}} -- create new object at front
		move theEllipse to after page item -1 of layer 1 -- move it behind the backmost object
	end tell
end tell

 

JSX:

var doc = app.activeDocument

var pathItems = doc.layers[0].pathItems

var newEllipse = pathItems.ellipse(100, 100, 400, 400)

newEllipse.move(pathItems[pathItems.length-1], ElementPlacement.PLACEAFTER) // this works

 

JXA:

var aiApp = Application('Adobe Illustrator') 

var doc = aiApp.documents[0] 

var newEllipse = aiApp.make({ new: 'ellipse', at: doc.layers[0], 
                              withProperties: {bounds: [100, -100, 500, 100]} })

newEllipse.move({ to: doc.layers[0].pageItems[-1].after }) // this fails

 

That’s a JSX defect: it doesn’t support beginning/end/before/after specifiers. Contrast appscript, which gets it right:

 

#!/usr/bin/env python3

from appscript import *

ai = app('Adobe Illustrator')

doc = ai.documents[1]

el = ai.make(new=k.ellipse, at=doc.layers[1], 
             with_properties={k.bounds: [100, -100, 500, 100]} )

el.move(to=doc.layers[1].page_items[-1].after) # this works

 

And there are lots of other bugs and omissions as well. Many of which I reported while JXA was still being developed; most of which they ignored. I’m not kidding when I say JXA is not fit for purpose: I wrote appscript and several other production-apple event (“AppleScript”) bridges over the last 20 years, and Python 3 + appscript still drives my own high-end AI automations, so I know this stuff way better than JXA’s authors ever did.

 

The real deal-killer though is that none of JXA’s bugs and omissions will ever be fixed, because Apple has already abandoned it and scrapped the department that wrote it. So adopting JXA for your own workflows now is a fool’s errand.

 

If you want to use JavaScript then use Adobe’s JSX (ES3), and let Adobe know (politely) that you’re keen for them to bring UXP (Node) to AI as quickly as possible.

 

(I am currently investigating TypeScript as a modern, forwards-compatible option for future AI automations, as TS runs on everything from ES3 to the latest Node. But I do wish Adobe would hurry up with UXP as that will greatly simplify life all round.)

 

If you need to integrate with other Mac applications then use AppleScript—and pray that Apple doesn’t let it rot too quickly, as the likelihood of them ever creating a competent modern successor to AppleScript is roughly nil.

 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 26, 2021 Mar 26, 2021

Copy link to clipboard

Copied

LATEST

Wow thanks for sharing your experience!

I haved used JXA in the past for one simple purpose, which is to use JSON in the middle of a bunch of AppleScript stuff. I have not touched much Mac in a while though, but this proves that JXA is a dead-end for sure!

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines