Copy link to clipboard
Copied
Here is what I have right now. It is a little clunky in the way it works, and I would just like to make it a bit slicker.
I have a script on startup that creates a Menu item with a dropdown submenu item. when you click on the submenu item, it starts a script.
The first thing the script does is pop up a message box that tells them that two dialog boxes are going to popup. The first one asking them to choose the location of an xml file and the second dialog box that ask them to choose the location of their image folder. After they finish choosing their folder in the second dialog, the script takes those two values, makes them variables, and continues to run the rest of the script.
Here is what I would like it to do..
1. open a dialog window with two input fields, two "browse" buttons, and OK and CANCEL buttons
2. when you click the first browse button next to the first input field, it will open a file dialog window. You select your file and the file string will populate the input field
3. when you click the second button next to the second input field, it opens a folder dialog window. You select the folder and the string populates the second input field.
4. when you click OK, it feeds the values in the input fields to a script.
I already have scripts to that open the file and folder dialogs, but what I can't figure out how to do is to start and run a script from a button press, in this case, when the OK button is pressed. It is probably an onClick, but I haven't been able to find any examples of what the syntax would be.
The closest I have found is in the Beginning ScriptUI document that was on Jongware's site, in the section on Communication between windows. But that opens each of the windows with a different script and not using a button press to call a script.
As always, any point in the right direction is very much appreciated. thanks.
1 Correct answer
ScriptUI windows and the JS file dialog boxes don't communucate. To get a return value from a file dialog, you'd do something like this:
myFile = Folder (myFolder).openDlg ("Select some files");
if (myFile === null)
// return, do nothing
The JavaScript Tools Guide CSx (see the ESTK's Help menu) documents several file and folder selection dialogs.
Peter
Copy link to clipboard
Copied
> It is probably an onClick
It is indeed. You were looking in the wrong place in that guide. Look in the section "Responding to button presses".
Peter
Copy link to clipboard
Copied
Thanks for the reply Peter. I looked in the section you suggested, and see an example of the onClick, but i am still at a loss as to use it to call another script. My latest attempts was something like this...
var f2 = w2.add ("button", undefined,"Remove Menu");
f2.onClick = function()
{
var f = File('C:\Users\me\AppData\Roaming\Adobe\InDesign\Version 7.5\en_US\Scripts\Scripts Panel\Scripts\MenuTest_1.jsx');
$.evalFile(f);
}
but it doesn't appear to do anything. I am not getting any error messages or any indication that anything is wrong, it just doesn't seem to do anything at all.
Am I on the right track, and do you see anything obvious that would not cause it to work, or am I going in a completely wrong direction.
Copy link to clipboard
Copied
so playing around with it a little more, I am getting closer to where I need to be, but not quite there yet. I have changed what I tried previously to this...
f2.onClick = function()
{
var SCRIPTS_FOLDER = "/Users/me/AppData/Roaming/Adobe/InDesign/Version 7.5/en_US/Scripts/Scripts Panel/Scripts/";
var Script1 = File(SCRIPTS_FOLDER + "MenuTest_1.jsx");
$.evalFile (Script1);
}
and this worked, but now the issue I am running into is that one of the actual scripts i need to open is a .vbs script, and for some reason, this doesn't seem to be working when trying to run it.
Is there a special way I would need to call a .vbs file, or can a .jsx not call a .vbs script?
Copy link to clipboard
Copied
Instead of $.evalFile(), use app.doScript(), in which you can specify a script language. I believe the form is something like this:
app.doScript (Script1, ScriptLanguage.VISUAL_BASIC);
but do check the object-model viewer to check the correct form.
Peter
Copy link to clipboard
Copied
thanks Peter. that was the correct form.
The next piece of the puzzle is getting the file string info from the dialog box. In the example in the ScriptUI guide in the COMMUNICATION BETWEEN WINDOWS section, you created both windows and their input fields, and were able to give them different names in order to target them in the second script, copying the text from the first window to the second.
But with the file dialog box, I see a way to give it a title, but not a "name". So when I tried something like Window.find("dialog","Window Title"); it didn't work.
So do you know if there is a specific name given to dialog boxes by default created using the File.openDialog method in order to target them?
and secondly, how would you grab the return value from the dialog? I have tried things like window.returnValue which should be valid JS, but I cannot find any reference to it, or anything like it, in the Object Model Viewer.
Thank you for your help.
Copy link to clipboard
Copied
ScriptUI windows and the JS file dialog boxes don't communucate. To get a return value from a file dialog, you'd do something like this:
myFile = Folder (myFolder).openDlg ("Select some files");
if (myFile === null)
// return, do nothing
The JavaScript Tools Guide CSx (see the ESTK's Help menu) documents several file and folder selection dialogs.
Peter
Copy link to clipboard
Copied
I think what your looking for is the value from entry in the text field? To get this value after the window closes you would use your variable name that you created the entry field with.
So it would be something like this i think. var myColors=myColorsFieldOne.text; myColorsFieldOne being the dialogs variable.
Copy link to clipboard
Copied
Thanks Gotterman, but the issue I was having was that the dialogs I was opening were not being created by me. They were more like OS generated windows. So I am not able to give the window a name, or the input field a name in order to reference it.
Peters response was actually correct, although I did have to open the folder dialog a bit differently to get it to work. I had to use a style that I got from Jongware in a previous thread, but the concept that Peter showed in the last post pointed me in the right direction.
I just have one more piece to figure out, how I am going to pass the variables to another script, but I think that is something i will have to work out on my own.
For anyone who is curious, here is the code I came up, modifying and combining some of Peters examples from the book plus the help he gave me in this thread. The alert after closing the dialog is just for testing to show that the values are being held by the variables so I can use them else where.
function mySnippet(){
//<fragment>
#target indesign;
#targetengine "session";
var w2 = new Window("palette", "Window 2", undefined, {resizeable: true});
var e2 = w2.add ("edittext"); e2.characters = 30;
var e3 = w2.add ("edittext"); e3.characters = 30;
var f2 = w2.add ("button", undefined,"Browse XML");
var f3 = w2.add ("button", undefined,"Browse Folder");
var f4 = w2.add ("button",undefined,"SAVE AND RUN");
var tf
var tfo
f2.onClick = function() {
tf = File.openDialog("Select your XML File","*.xml");
if (tf != null)
{
e2.text = tf;
}
}
f3.onClick = function() {
var tfol = new Folder("~/My Documents")
tfo = tfol.selectDlg("Get Folder");
if (tfo != null)
{
e3.text = tfo;
}
}
f4.onClick = function()
{
w2.close();
alert ("xml value: " + tf + "\nfolder value: " + tfo);
}
w2.show();
//</fragment>
}
Copy link to clipboard
Copied
This may help in passing your variables to anothe script. I used this little snippet(not my own) to have entry fields remember what the user typed in the last time they ran the dialog. This may help you write to another script. This one rewrites itself.
var schlNamePos = 1002 ;
var updateFile = function(n){
var f = File(app.activeScript);
if ( f.open('e') ){
f.seek(schlNamePos);
f.write(''+n);
f.close();
}
}
updateFile(mySchoolName);
Copy link to clipboard
Copied
Thanks. That will probably come in helpful at some point. Unfortunately it won't help me at the moment.
However, I did figure out how to pass the variables based on this post. I am setting them up as environment variables in my JSX file like so..
f2.onClick = function() {
tf = File.openDialog("Select your XML File","*.xml");
if (tf != null)
{
e2.text = tf;
tf = tf.absoluteURI
$.setenv("myFileVar",tf)
}
}
and then grabbing them in my VBS script like this..
Set WshShell = CreateObject("WScript.Shell")
Set objEnv = WshShell.Environment("Process")
myFileName = objEnv("myFileVar")
The problem that I am running into is that the file and folder dialogs don't give me an absolute path, but a path that is relative to the startup disk. It is discussed in this post and I haven't found any way to get around it yet. From the discussion, it doesn't sound like there is a work around, so I may just be out of luck in trying to do what I want to do. But I am going to keep trying for a bit longer.
Copy link to clipboard
Copied
The problem that I am running into is that the file and folder dialogs don't give me an absolute path, but a path that is relative to the startup disk. It is discussed in this post and I haven't found any way to get around it yet. From the discussion, it doesn't sound like there is a work around, so I may just be out of luck in trying to do what I want to do. But I am going to keep trying for a bit longer.
I think that thread is somewhat confused about how file path works, and also that is Mac OS -specific. Can you please give a very specific example of the problematic file path? With real actual values and show how it is a problem?
(Environment variables? Wow. I would have hoped there was a better way. But I'm not a VB programmer.)
Copy link to clipboard
Copied
So for example, when I open a file dialog and I choose a file in My Documents, I get ~/Documents/DM_Layout_Test_2.xml returned
When I choose a folder, like MyDocuments/My Pictures I get this returned.. ~/Documents/My%20Pictures
If I choose something like the Root of C: i get /c returned.
If I choose something on a separate drive like this... M:\XMLDocs\DM_Layout_Test_2.xml I get this... \m\XMLDocs\DM_Layout_Test_2.xml
None of which my code seems to like. If I hard code the paths like... C:\Users\erich\Documents\DM_Layout_Test_2.xml Then it works fine.
So ultimatly what I would like is to either A) find a way to get the absolute path and be able to use that or B) figure out a way to work with what I am getting returned.
I have tried: .Parent, .FullName, .fsName but nothing seems to work. I thought about trying to do an alias, but I haven't figured out how to make that work yet.
RE: Environment variables - I am certainly open to another way of doing it, that was just the first solution I came across that worked.
Copy link to clipboard
Copied
As I said earlier, read up on files in the JavaScript Tools Guide CSx guide (ch. 3, File system access). You'll read there, for instance, that ~ is the desktop, and that /c/dir is the platform-independent notation for c:\dir. And as John mentioned, environment variables are not necessary (and should maybe not be used for your purpose at all). Instead, you can write script data to a disk file, or use an application or a document label.
Peter
Copy link to clipboard
Copied
I have been back and forth through Chapter 3 today at least 3 times, and I am just as confused as ever.
I am just going to assume that Environment variables are a bad way to go based on Peter and Johns comments, although I don't actually know why, so I have also tried to find out more about application and document labels, but I can't find any reference to them. I thought I might also try doing it as a text file, but am not having any luck going that way either so far.
So can someone give me a direction as to where I can find more info on application and document labels, or maybe an example of how to use them? Or if you guys think using a file would be better for what I am trying to do, let me know and I will try to get that to work.
Copy link to clipboard
Copied
For the app:
app.insertLabel("foo", "my info");
app.extractLabel("foo");
For a doc:
myDoc.insertLabel etc.
HTH,
Ariel
Copy link to clipboard
Copied
BigGunN: sorry for the delay, I've been swaaaaamped lately.
When I choose a folder, like MyDocuments/My Pictures I get this returned.. ~/Documents/My%20Pictures
Are you looking at the .fsName property? It's not convenient for me to test under Windows right now, but on a Mac,
>> f=File.openDialog()
~/Desktop/frap.pdf
>> f.fsName
/Users/writer/Desktop/frap.pdf
>> f.absoluteURI
~/Desktop/frap.pdf
So, don't use absoluteURI. Does that fix it for you?
With respect to passing arguments, I'm afraid I have to disagree with Peter and Ariel:
And as John mentioned, environment variables are not necessary (and should maybe not be used for your purpose at all). Instead, you can write script data to a disk file, or use an application or a document label.
That's even worse then using an environment variable -- it's active bad if you might have multiple simultaneous button presses being happening at the same time, for instance.
Instead, I would expect the right solution is to call your VB with arguments, formal parameters that are passed from one function to another. But environment variables are OK. They are just more effort than they need to be and kind of ugly. But they're functional. I'd leave them be until you have something that works and only then worry about clean-up.
Copy link to clipboard
Copied
John,
Thank you for the response. The fsName was it. I swear I tried it before, but for some reason I didn't think it worked. Probably one of those situations where I was trying thing after thing in different combinations, and I overlooked an obvious combination. Or maybe I forgot to restart ID, so it was reading old code.
Whatever the reason, it looks like using the fsName did what I needed it to do. I am now getting the full path that I needed to read my XML file and my image files. That was the last major part of my puzzle.
Do you know if there will be any issue with giving these scripts to someone using a mac? I don't have a way to test on a mac, and I don't know what kind of machines my client will be using. But can it be assumed if a script works on one machine, it will work on any type regardless of the languages being used?
I am going to stick with the environment variables for now, just because they are working, although I am very curious as to how to call VB with arguments, as it seems like it would be a more elegant solution. Do you just add the arguments in the doScript call? And then how do you refer to them in the script your calling?
Anyway, thank you, thank you. And thank you everyone that participated in this thread. I wouldn't have been able to get this far without your help.
Copy link to clipboard
Copied
Well, VB is Microsoft-only. So if your scripts use VB, there is no way they will work on a Mac.
With respect to Javascript, unless you use obviously platform-specific features, your script should be portable. I wasn't quite sure about the filesystem specifics.
I'm not sure how you refer to arguments in VBScript. I beleive there are several examples in the documentation, bt I don't have time to go look around for the mright now.
Copy link to clipboard
Copied
thats alright. I appreciate all the help.
Copy link to clipboard
Copied
I searched over all Adobe forums for script like yours, so to replace (without RegExp) just single character inside of text file.
But I found one problem I don't know whether there is a tweak for. Namely following script replace not only found character, but length of characters starting from looked for character, so if content of text file is: 0123456789
And I want to replace number 5 for letter 'A' there is no problem, I'm getting: 01234A6789
But if I like to change that for 'ABC' I'm getting 01234ABC89 (instead of 01234ABC6789)
Can anyone help me to change this script it worked the way I need:
fle = File('~/desktop/Nums.txt')
fle.open('e'), i = 0; while(!fle.eof) {
fle.seek(i); if (fle.readch(i) == '5')
fle.seek(i), fle.write('ABC'); i++
}
fle.close()
Copy link to clipboard
Copied
> replace (without RegExp) just single character inside of text file
Why? That's like 'disassemble this four-stroke engine without using spanners'. So get used to RegExp and do as follows:
find = '5';
change = 'ABC';
re = RegExp (find + '.{' + (change.length-1) + '}');
fle = File('~/desktop/Nums.txt');
fle.open('r');
s = fle.read();
fle.write (s.replace (re, replacement));
fle.close();
P.
Copy link to clipboard
Copied
That was only very little example of something much bigger I want to achieve. So I did that simple, and mentioned to not use RegExp in the code not without reason. Actually I'm quite good with RegEx. Few years ago I wrote this code in just 2 days to change that the other one:
Action Manager (Script Listener) code converter script!
But now I want to do something different where RegEx is too slow for the files with over few tousends of lines where some characters must be changed to others. The solution is using kind of method like in the sample I left. That gives much faster performance. The only what I have to figure out is how to change one character into few others without cutting the length of fallowed characters from original text.

