Copy link to clipboard
Copied
Last week I wrote a simple script that interacts with my document and exports layers as images.
The script works great, but I thought I'd add a nice UI to it before I release it to the world, so I spent last Saturday making the GUI.
Now, I've built my UI, and I hook it up to my existing code.
If I trace the current "activeDocument" at the beginning of my code, before I instantiate the window, I get what you would expect:
alert("Current Window:"+.app.activeDocument);// Traces - Current Window:[Document myTestDoc.ai]
Now if I try to reference my document from the window click handler, or after I've closed my window I get this:
alert("Current Window:"+.app.activeDocument);// Traces - Current Window:[Document]
alert("Current Window:"+.app.documents[0]);// Also Traces - Current Window:[Document]
The script can still see the document, but suddenly it can't introspect it.
"app.documents" yields the correct number of open documents,
"app.name" yields the correct application "Adobe Illustrator"
but anything like the following will fail.
alert(app.documents[0].layers.length);
Any advice would be massively appreciated.
thanks,
-J
cool, maybe we find a simple as possible solution.
you don't need the alert, you must set at begin:
#targetengine ????? (I heard "not main" but this seems to be not true, it can be main?)
don't ask me why
...#target illustrator
#targetengine another
var btnPnlResource ="panel { orientation:'row', \
text: 'Push Button to Test', \
testBtn: Button { text:'Test' }, \
}";
var dlg = new Window("palette", "Select PATH");
dlg.btnPnl = dlg.add(btnPnlResource);
dlg.show();
dlg.btnPnl.testBtn.onClick = traceDoc;
//alert("M
Copy link to clipboard
Copied
Hi John,
it's not the palette problem?
can you post the code of the window?
I think, alert: [Document], is not the Doc(instance) but the constuctor ("class").??
Chris
Copy link to clipboard
Copied
Hello Chris,
Thank you for the response.
My code is huge, so I took a MUCH simpler example from the "Sample files" that comes with ExtendScript ToolKit.
(specifically SnpCreateSlider.jsx)
The only change I've made to the code is that I've added a nowTraceAnythingAboutCurrentDocument() function at the bottom.
It is exhibiting the same behavior for me as my code, so maybe I am thinking incorrectly about how the UI dialogs are supposed to work.
Anyway, any and all help is much appreciated.
thanks
-J
//////////////////////////////////////////////////////////////////////////// // ADOBE SYSTEMS INCORPORATED // Copyright 2007 Adobe Systems Incorporated // All Rights Reserved // // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the // terms of the Adobe license agreement accompanying it. If you have received this file from a // source other than Adobe, then your use, modification, or distribution of it requires the prior // written permission of Adobe. ///////////////////////////////////////////////////////////////////////////// /** @fileoverview Shows how to use a slider ScriptUI component. @class Shows how to use a slider ScriptUI component. <h4>Usage</h4> <ol> <li> Open this file and run it in the ExtendScript Toolkit. You can choose as the target any application that supports ScriptUI <li> Move the slider in the displayed dialog and watch the label update. </ol> <h4>Description</h4> <p>Creates a dialog containing a slider and a text component. The current value is reflected in the text.<br /> @constructor Constructor. */ function SnpCreateSlider () { this.windowRef = null; } /** Create a window, add a slider control and a text label. Define behavior for the slider that updates the text in the label. @return True if the snippet ran as expected, false otherwise. @type Boolean */ SnpCreateSlider.prototype.run = function() { var retval = true; // Create a palette-type window (a modeless or floating dialog), var win = new Window("palette", "SnpCreateSlider", [150, 150, 600, 300]); this.windowRef = win; // Add a panel to contain the components win.pnl = win.add("panel", [10, 10, 440, 100], "Move slider around"); // Add some labels that describe the state of the slider win.pnl.minLbl = win.pnl.add("statictext", [20, 47, 35, 60], "0"); win.pnl.curLbl = win.pnl.add("statictext", [115, 47, 170, 60], "100"); win.pnl.maxLbl = win.pnl.add("statictext", [210, 47, 250, 60], "200"); win.pnl.displayTextLbl = win.pnl.add("statictext", [290, 20, 380, 40], "Current value:"); win.pnl.displayLbl = win.pnl.add("statictext", [385, 20, 425, 40], "100"); // Add a slider control win.pnl.sliderCtrl = win.pnl.add("slider", [20, 20, 230, 45], 100, 0, 200); // Add buttons win.resetButton = win.add("button", [25, 110, 125, 140], "Reset"); win.doneButton = win.add("button",[320, 110, 420, 140] , "Done"); // Define behavior for when the slider value changes win.pnl.sliderCtrl.onChanging = function() { var val = Math.round(win.pnl.sliderCtrl.value); // Update the label text with the current slider value. win.pnl.displayLbl.text = val; }; // Define behavior for the "Exit" button win.doneButton.onClick = function () { win.close(); nowTraceAnythingAboutCurrentDocument(); }; // Define behavior for the "Reset" button win.resetButton.onClick = function() { win.pnl.sliderCtrl.value = 100; win.pnl.curLbl.text = 100; win.pnl.displayLbl.text= 100; } // Display the window win.show(); return retval; } /** "main program": construct an anonymous instance and run it as long as we are not unit-testing this snippet. */ if(typeof(SnpCreateSlider_unitTest) == "undefined") { new SnpCreateSlider().run(); alert("Before the window, this works: app.documents[0].name="+app.documents[0].name); } function nowTraceAnythingAboutCurrentDocument(){ alert("I can still get the number of documents: app.documents.length = "+app.documents.length); //works... alert("And even a vague reference to the current document: app.activeDocument: "+app.documents[0]+" but the next line will fail to run."); //finds [Document], but it's not accessible... alert("But this fails to run for me:"+activeDocument); //this flat out fails. alert("This too"+app.documents[0].name); //this too. }
Copy link to clipboard
Copied
yes, palette is the problem, (i think so, whitout testing).
try
var win = new Window("dialog"
instead of
var win = new Window("palette"
chris
Copy link to clipboard
Copied
That was it. Thanks Chris!
Copy link to clipboard
Copied
I have some functionality in my UI window that requires "palette."
So... Dare I ask, how the heck do you utilize a palette window with Illustrator?
Are there any examples anywhere that actually DO something with AI?
thanks,
-J
Copy link to clipboard
Copied
No way John, not with js.
only thing... no i dont tell it... okay i tell it.
a "dialog" with the creation propertys independent:true and/or(?) minimizeButton:true (which is illegal)
and a mouse with "focus under cursor" feature.
and you can, with luck, and massiv double click attacks, get the focus on the document for milliseconds
to change selection or whatever.
but then there is a redraw problem, so yon dont see if selection is changed.
is that funny? I don't know
do you really need this? your example runs for me with "dialog".
so, what functionality requires "palette."?
Copy link to clipboard
Copied
Just a untested idea, John:
dialog.onClick:
dialog.close()
paletteScriptFile.execute() // this should not return back to onclick function
make your changes in Doc. possible because dialog is killed. But Script has no access to Doc, so:
palette.onClick:
palette.close()
dialogScriptFile.execute() // this should not return back to onclick function
what's about variables? store it in a file?
???
Chris
Copy link to clipboard
Copied
chris you're a genius. I'll try this weekend and report back.
awesome idea!
Copy link to clipboard
Copied
Well, at least it was an exciting afternoon. While it was a great idea, it appears that Adobe has locked us down pretty hard.
I've tried launching an external script with execute, but execute only opened the script in the Extendscript Toolkit.
var btnPnlResource ="Panel { orientation:'row', \
text: 'Push Button to Test', \
testBtn: Button { text:'Test' }, \
}";
var dlg = new Window("palette", "Execute Test");
dlg.btnPnl = dlg.add(btnPnlResource);
dlg.show();
dlg.btnPnl.testBtn.onClick = traceDoc;
function traceDoc(){
dlg.close(1);
alert(app.documents[0]);
//there of course needs to be a file here:
(new File("~/Desktop/anotherScript.jsx").execute();
}
incidently:
illustrator.executeScript("~/Desktop/myScript.jsx"); // also failed
I tried the roundabout way by creating a bridgetalk connection, running the script in another application and then triggering a callback when it completed, but whenever the palette opens up, it immediately kills all relationship to the specific document object in Illustrator.
var bt = new BridgeTalk;
// send this msg to the Adobe Bridge CS4 application
var targetApp = BridgeTalk.getSpecifier( "bridge");
bt.target =targetApp;
// the script to evaluate is contained in a string in the "body" property
bt.body = "var btnPnlResource =\"Panel { orientation:'row', text: 'Push Button to Test', testBtn: Button { text:'Test' } }\"; \
var dlg = new Window(\"palette\", \"Execute Test\");\
dlg.btnPnl = dlg.add(btnPnlResource);\
dlg.show();\
dlg.btnPnl.testBtn.onClick = traceDoc;\
function traceDoc(){\
dlg.close(1);\
}; ";
bt.onResult = function(returnBtObj) {//fails
alert(app['documents'][0] .layers[0].name);
}
bt.send();
This is really wierd.
I'd love to hear from someone at Adobe as to why palattes are nerfed.
Is it a security thing or is it a bug?
I'll be happy to try any other workarounds if you can think of any.
best,
-J
Copy link to clipboard
Copied
All is not lost.
Here's a really weird workaround...
var btnPnlResource ="Panel { orientation:'row', \
text: 'Push Button to Test', \
testBtn: Button { text:'Test' }, \
}";
var dlg = new Window("palette", "Execute Test");
dlg.btnPnl = dlg.add(btnPnlResource);
dlg.show();
dlg.btnPnl.testBtn.onClick = traceDoc;
alert("Move me, don't close me.");
function traceDoc(){
dlg.close(1);
//alert(app.documents[0]);
alert("works!");
var nf = new File("~/Desktop/test2.jsx");
nf.execute();
}
This works for me, but it's wonky as hell. basically, I create an alert window which keeps the palette from closing, then, if I move the alert out of the way, boom, I have a fully functional palette, it fires an execute script, and the script has document control... I have achieved my goal, but, I'd love to find a way to keep the palette open without having to instantiate the popup window... I'll keep plugging at it. Let me know if you find anything cool.
-J
Copy link to clipboard
Copied
OK, I can run this from extendscript Toolkit without any issues. If I run from illustrator then I need the above "alert hack".
Essentially I took your idea from above Chris, and blended it with your .execute() post, and got this. No need for a temp file.. Because I write the second script on the fly, from within the first one.
The code is wonky, but it does what I want, and the end user shouldn't have to worry about it. I THINK this is the winning formula... Thanks for the help, and the inspiration!
cheers,
-J
var btnPnlResource ="Panel { orientation:'row', \
text: 'Push Button to Test', \
testBtn: Button { text:'Test' }, \
}";
var dlg = new Window("palette", "Execute Test");
dlg.btnPnl = dlg.add(btnPnlResource);
dlg.show();
dlg.btnPnl.testBtn.onClick = traceDoc;
//alert("Move me, don't close me.");
function traceDoc(){
dlg.close(1);
var myFile = new File("~/Desktop/test2.jsx");
var content="alert('Written from script1: current document name:'+app.activeDocument.name)";
myFile.open("e");
myFile.writeln(content);
myFile.close();
myFile.execute();
}
Copy link to clipboard
Copied
cool, maybe we find a simple as possible solution.
you don't need the alert, you must set at begin:
#targetengine ????? (I heard "not main" but this seems to be not true, it can be main?)
don't ask me why
#target illustrator
#targetengine another
var btnPnlResource ="panel { orientation:'row', \
text: 'Push Button to Test', \
testBtn: Button { text:'Test' }, \
}";
var dlg = new Window("palette", "Select PATH");
dlg.btnPnl = dlg.add(btnPnlResource);
dlg.show();
dlg.btnPnl.testBtn.onClick = traceDoc;
//alert("Move me, don't close me.");
function traceDoc(){
// !!!!!!!! dlg.close(1);
var myFile = new File("~/Desktop/test2.jsx");
var content= "#target illustrator\n" +
"#targetengine another\n" +
"alert('Written from script1: AREA:'+app.activeDocument.selection[0].area)";
myFile.open("w");
myFile.write(content);
myFile.close();
myFile.execute();// !!!!!!!dlg.show() // !!!!!!!!!!!!!!!
}
problem is, the estk asks "should I do", and need some time to react.
faster but only for windows:
(test2.jsx still exists)
#target illustrator
#targetengine another
var appPath = app.path + "/Support%20Files/Contents/Windows/illustrator.exe " ;//unix?
var shellScriptPath = "~/desktop/AiShellScript.bat" ;
var aiScriptPath = "~/desktop/test2.jsx" ;
function Schell(){
var ssp = new File( shellScriptPath ) ;
ssp.open("w") ;
var tex = "@echo off\n"+ // unix?"Start \"\" \"" + File(appPath).fsName + "\" " + File(aiScriptPath).fsName + "\"" ; //unix?
ssp.write( tex ) ;
ssp.close() ; ssp = null ;
}
var btnPnlResource ="panel { orientation:'row', \
text: 'Push Button to Test', \
testBtn: Button { text:'Test' }, \
}";
var dlg = new Window("palette", "Select PATH");
dlg.btnPnl = dlg.add(btnPnlResource);
dlg.show();
dlg.btnPnl.testBtn.onClick = traceDoc;
function traceDoc(){
Schell();
var myFile = new File( shellScriptPath );
myFile.execute();
}
but, which case ever, interesting is
-that we don't need to close the window.
- that we can run more then 1 script
- that we can't look at the variables between scripts, even if (declared)targetengine is the same in both scripts, i think it is not really the same.
edit: maybe THIS IS ALL CRAP, because:
illustrator12.executeScript(myAIScript);
but it seems illustrator can't be it's own targetapplication???
try{
illustrator.executeScript( "~/desktop/test2.jsx" );
}catch(e){alert(e)}
this gives me a syntax error
Copy link to clipboard
Copied
Hot...It works!
I wrapped the #targetengine in a try/catch so it doesnt' complain when run from extendscript toolkit.
Here is the link to my final script. Thanks for all the help!Hopefully this post serves as a guidepost for other folks to make some killer interactive scripts for AI.
Happy scripting, and thanks again Chris!
-J
Copy link to clipboard
Copied
It seems there is a fault type in your credits / greating
.. you written chris Ogebab instead Chris Gebab
Copy link to clipboard
Copied
Whoops, I made him Irish... Thanks for the catch. Fixed.
Copy link to clipboard
Copied
Thanks for the Credits
Nice script John.
Bah, Irish or whatever, i don't care
The (my) crude "shell" Hack from above grips me.
I'm really interested to know what happens if you run the following under Macintosh.
Under windows, a selected script will be executed, a selected Document will be opened.
a shellscript should be created.
Would one be so good and try it?
thanks
Chris
function callShell(){
var sys = File.fs ;
switch(sys){
case "Windows":
break;
case "Macintosh":
var appPath = app.path + "/Configuration/Contents/MacOS/Adobe%20Illustrator" ;
// var shellSkript = new File( "~/AIjs/" + shellName + ".command") ;
var shellSkript = new File( "~/AIjs/test.command") ;
alert(shellSkript.fsName)
shellSkript.open("w");
var tx = "#!/bin/sh\nps | grep -i -e illustrator.exe 1>/dev/null 2>&1 || exit\n"+
"\"" + File(appPath).fsName + "\" \"" + skriptPfad.fsName + "\"" ;
shellSkript.write( tx ) ;
shellSkript.close() ; shellSkript = null ;
alert("Shellscript is in your Home Directory, use Quicksilver to create a hotkey for it")
break;
case "Unix":
alert( "Unix" )
break;
default:
alert( "default\n"+sys )
}
}
var skriptPfad = File.openDialog("Select Script ") ;
if (skriptPfad){
var shellFolder = new Folder( "~/AIjs" ) ;
if( shellFolder.exists == false ) shellFolder.create() ;
var skriptName = skriptPfad.displayName.split(".")[0] ;
var shellName = "AI_skript_" + skriptName ;
callShell() ;
}
Message was edited by: chris gebab Code updateted
Copy link to clipboard
Copied
Unfortunately I am a Windows only developer, so I can't test Mac.
I can give it to my graphics guy on Monday if he's not too busy.
Copy link to clipboard
Copied
Hi Chris,
I will try your script on my MAC at office on monday and will make a report (if no body don't do)
See u, art.chrome
Copy link to clipboard
Copied
Hi Chris,
var appPath = app.path + "/Configuration/Contents/MacOS/Adobe%20Illustrator" ;
/configuration/ isn't here...
real path is:
/Contents/MacOS
where appPath is :
/Applications/Adobe\ Illustrator\ CS4/Adobe\ Illustrator.app/
var shellSkript = new File( "~/AIjs/test.command") ;
it write a file at : User / AIjs/test.command
content:
#!/bin/sh
ps | grep -i -e illustrator.exe 1>/dev/null 2>&1 || exit
"/Applications/Adobe Illustrator CS4/Contents/MacOS/Adobe Illustrator" "/Users/MyUserName/Desktop/AIjs/test.jsx"
*******
ps | grep -i -e illustrator.exe 1>/dev/null 2>&1 || exit
.exe doesn't exist on mac, extension is .app (not exactly, in fact .app it's a package/folder but it appears as an application in browse, you can see inside only if you ask for "extract")
Correct run is:
/Applications/Adobe\ Illustrator\ CS4/Adobe\ Illustrator.app/Contents/MacOS/Adobe\ Illustrator
i've tried with:
ps | grep -i -e illustrator.app 1>/dev/null 2>&1 || exit
still in shell/terminal, it return:
logout
[Operation termined]
shell/terminal is broken/termined
ps | grep -i -e Adobe\ Illustrator 1>/dev/null 2>&1 || exit
or
ps | grep -i -e Adobe\ Illustrator 1>/dev/null 2>&1 || exit
or again
ps | grep -i -e /Applications/Adobe\ Illustrator\ CS4/Adobe\ Illustrator.app/Contents/MacOS/Adobe\ Illustrator 1>/dev/null 2>&1 || exit
same result...
below an exemple of illustrator task (command: ps -A):
1072 ?? 0:12.62 /Applications/Adobe Illustrator CS4/Adobe Illustrator.app/Contents/MacOS/Adobe Illustrator -psn_0_299081
1072 is PID (process ID)
0:12.62 <- how many time is running
-psn_0_299081 (i don't know.. but it change at each launch)
Unfortunately i don't know what mean
| grep -i -e application.exe 1>/dev/null 2>&1 || exit
I guess just you test if illustrator task is running or not, if yes shellscript continue and execute illustrator which is run script(jsx), else it close..
So i've tried still directly in shell/terminal:
/Applications/Adobe\ Illustrator\ CS4/Adobe\ Illustrator.app/Contents/MacOS/Adobe\ Illustrator "/Users/MyUserName/Desktop/AIjs/test.jsx"
where test.jsx is simple alert("ok");
Illustrator is running, but no script it was executed in fact , it seems me that when you ask for execute script, illustrator open (but hide) extentscript tool kit.. but may be i'm wrong..
I hope that this report could help you
if you have any suggest / questions please feel free to ask me.
art.chrome
N.B.: when i launch test.command directly in shell/terminal the result is permission denied
also:
/Applications/Utilities/Adobe\ Utilities.localized/ExtendScript\ Toolkit\ CS4/ExtendScript\ Toolkit.app/Contents/MacOS/ExtendScript\ Toolkit /Users/MyUserName/Desktop/AIjs/test.jsx
this open ExSTK, and open test.jsx for edit, but not run...
Message was edited by: artchrome (added N.B.:)
Copy link to clipboard
Copied
Wow, at first, thank you very much for the detailed explanation.
the right paths helps much
yes, you guess right, hm, ...grep -i -e illustrator..., should also work here.
where test.jsx is simple alert("ok");
Illustrator is running, but no script it was executed
in fact , it seems me that when you ask for execute script, illustrator open (but hide) extentscript tool kit.. but may be i'm wrong..
also with test.js instead of .jsx?
I don't know if the double quotes in the command-line are necessary?
if param is a doc instead of script?
Is the script executed if you drag it on the illustrator Window? (like on windows xp)
......the result is permission denied
maybe this is a problem of a not set (and not automaticly setable?) executable bit. then it breaks the whole approach
other options:
-Applescript
-estk
but i think both will not work fast enough?
....this open ExSTK, and open test.jsx for edit, but not run...
#target Illustrator is set?
Art, thank you again
Chris
Copy link to clipboard
Copied
chris gebab wrote:
Wow, at first, thank you very much for the detailed explanation.
the right paths helps much
yes, you guess right, hm, ...grep -i -e illustrator..., should also work here.
it quit alway.. (that illustrator running or not). But i don't know which info grep should be return.
i'v tried
ps | grep -i -e Illustrator
and it returns:
3543 ttys000 0:00.01 grep -i -e Illustrator
isn't curious ?
...
also with test.js instead of .jsx?
same effect.
I don't know if the double quotes in the command-line are necessary?
You right, but with or without it's same result
if param is a doc instead of script?
It seems that Illustrator don't accept any parameter, (curious).. I'm not fully familiarized with MAC OS / Unix but in all case, whatever i sent to illustrator , it returned nothing except launch illustrator (no result, no error, like as if it don't check for parameter)
Is the script executed if you drag it on the illustrator Window? (like on windows xp)
No way.., we can't execute js or jsx with drag/drop on illustrator,
drag /drop on ESTK, ESTK generate an alert something like that "Do you really want execute this script in illustrator CS4?"..
So if yes it run the script or if not, put ESTK is in edit mode on test.jsx/.js
maybe this is a problem of a not set (and not automaticly setable?) executable bit. then it breaks the whole approach
contrary to win XP, on mac os, you are running in something like that "limited users" but it minor limited than XP, we can install some appz, but some command / action require root authorisation (like as admin on XP).
Other options:
-Applescript
-estk
but i think both will not work fast enough?
I haven't enough knowledge (i know only the name , may be Muppet Mark could send his ideas) on Applescript..
....this open ExSTK, and open test.jsx for edit, but not run...#target Illustrator is set?
#target Illustrator is set Yes
See you, art.chrome
Copy link to clipboard
Copied
I have not looked all the way thru this topic. I think what you require is… a test file…
#target illustrator $.level = 0; app.userInteractionLevel = UserInteractionLevel.DISPLAYALERTS; alert('Hello "Art"');
Which I saved to my mac desktop… Called 'Test.jsx' Then take a look at the toolkit for…
$.evalFile (path[, timeout]);
I can't test this at the moment as Im at work on a CS2 mac.
Copy link to clipboard
Copied
Yep this worked for me…
#target illustrator var x = new File('~/Desktop/Test.jsx'); var y = '~/Desktop/Test.jsx'; $.evalFile(x); $.sleep(1000); $.evalFile(y);
Also samething calling from BridgeTalk message without problem…
#target bridge var aiScript = ""; aiScript += "var x = new File('~/Desktop/Test.jsx');" + "\n"; aiScript += "var y = '~/Desktop/Test.jsx';" + "\n"; aiScript += "$.evalFile(x);" + "\n"; aiScript += "$.sleep(1000);" + "\n"; aiScript += "$.evalFile(y);" + "\n"; btMessaging('illustrator', aiScript) function btMessaging(targetApp, script) { var bt = new BridgeTalk(); bt.target = targetApp; bt.body = script; bt.onResult = function(inBT) {alert('Result "BridgeTalk" Works??? I need CS5')}; bt.onError = function(inBT) {alert('Got it wrong again!!!')}; bt.send(5); // Timeout in seconds wow… }
Copy link to clipboard
Copied
Hi Muppet Mark,
Thanks for this script. May be i misunderstand your way, but the final goal (from Chris Gebab) is to run a script (test.jsx) at first launch of Illustrator. Have you an idea, may be in applescript ?
It seems it's ok for Windows XP, but it's different for MAC OS / Unix. Personnally i haven't enough knowledge regarding unix command. The first idea it was to check if an instance of Illustrator is running with ps / grep command, and launch Illustrator / ETSK for a script. For my part, i didn't succed to launch a script by illustrator or ETSK (in running mode, because i can launch ETSK but it's in standby in edit mode, openned on test.jsx)
Regards, art.chrome
Find more inspiration, events, and resources on the new Adobe Community
Explore Now