Copy link to clipboard
Copied
This is for FrameMaker, not InDesign, but it's basically a ScriptUI question.
It's also somewhat related to: https://community.adobe.com/t5/indesign-discussions/can-i-pass-arguments-to-include-script/td-p/1528...
Consider this simple code:
ShowWindow1();
ShowWindow2();
function ShowWindow1(){
var w = new Window ("palette", "Window 1");
btn1 = w.add ("button", undefined, "OK");
ckbx1 = w.add("checkbox", undefined,"Check Box");
w.add ("button", undefined, "Cancel");
btn1.onClick=function(){
alert("You clicked OK on Window 1");
}
w.show ();
}
function ShowWindow2(){
//w.close;
var w = new Window ("palette", "Window 2");
btn1 = w.add ("button", undefined, "OK");
w.add ("button", undefined, "Cancel");
btn1.onClick=function(){
alert("You clicked OK on Window 2");
alert(ckbx1.value);
}
w.show ();
}
I'm having a hard time understanding the following issues:
I actually have several scripts all using "win" as the name of the window and I want the scripts to close any open windows before opening the new one called out in the current script. I thought I would have an issue if the window had been closed previously, but it looks like I have an issue even closing the window if it is still open.
> I also want to avoid launching two identical windows if the script were run twice.
Check whether the window exists. If it doesn't, create it:
var w = Window.find ('palette', "Window 1");
if (!w) {
w = new Window ("palette", "Window 1");
...
...
}
w.show();
Similarly, to close an existing window, do this:
var w = Window.find ('palette', "Window 1");
if (w) {
w.close();
}
Issue 1 sounds as if it's still a problem with variable scope. Maybe check you variable (non-)declarations again.
> do I need to go through each of the scripts and make sure ALL the butttons and checkboxes use unique names?
That might be a good idea. But you can target specific controls by looking for them in specifuc windows. Use .find() to find a window, then use find() to find a named contro, in the window.
But another way of organising variables is to use a variable for a window, then
...Copy link to clipboard
Copied
> ckbx1 seems to be "global" - i.e. I don't have to pass it as an argument to ShowWindow2.
That's because it's not declared as a variable.
> w and btn1 do not appear to be global - the script interprets them correctly, even though they have identical names?
That's because they are declared as variables.
> w.close gives me an error, even though w should already be defined as window 1.
The two instances of w are local in their functions. That's why w.close() in ShowWindow2 causes an error.
Copy link to clipboard
Copied
Okay - if I remove var from in from of w in ShowWindow1, I still get a "w is undefined" on the w.close (probably should be w.close() in ShowWindow2.
More to the point: I have Script1.jsx, that opens a palette named "win." I have Script2.jsx, that also opens a palete named "win" (with different controls).
What commands can I add to each script to close any open "win" palettes, but not give an error if the palettes were previously closed. (I also want to avoid launching two identical windows if the script were run twice.)
Copy link to clipboard
Copied
Workaround - you can add a hidden label to the document or application that will tell you if window is open.
And maybe even "a reference" - but I'm not JS guy so just brainstorming.
Copy link to clipboard
Copied
> I also want to avoid launching two identical windows if the script were run twice.
Check whether the window exists. If it doesn't, create it:
var w = Window.find ('palette', "Window 1");
if (!w) {
w = new Window ("palette", "Window 1");
...
...
}
w.show();
Similarly, to close an existing window, do this:
var w = Window.find ('palette', "Window 1");
if (w) {
w.close();
}
Copy link to clipboard
Copied
Scope is a complex topic, but does this pattern help?
(function () {
// make `settings` a global property so
// everyone can see it (be careful with naming!)
$.global.settings = {
checkBoxValue: undefined,
};
ShowWindow1();
ShowWindow2();
function ShowWindow1() {
var w = new Window("dialog", "Window 1"),
btn1 = w.add("button", undefined, "OK"),
ckbx1 = w.add("checkbox", undefined, "Check Box"),
cancelButton = w.add("button", undefined, "Cancel");
ckbx1.onClick = function () {
settings.checkBoxValue = this.value;
};
btn1.onClick = function () {
alert("You clicked OK on Window 1");
w.close(1);
}
w.show();
}
function ShowWindow2() {
var w = new Window("dialog", "Window 2"),
btn1 = w.add("button", undefined, "OK"),
cancelButton = w.add("button", undefined, "Cancel");
btn1.onClick = function () {
alert("You clicked OK on Window 2");
alert('checkBoxValue = ' + settings.checkBoxValue);
w.close(1);
}
w.show();
}
})();
Copy link to clipboard
Copied
[removed]
Copy link to clipboard
Copied
@Marshall_Brooks -- If you want to address some button or other control in a different window, you shouldn't use global variables. Better to name the control and use X.find() to pick them up. See https://creativepro.com/files/kahrel/indesign/scriptui.html for details.
Copy link to clipboard
Copied
@Peter Kahrel -- Is there a way to close all open windows with one script? For example, if there were 20 open windows, your script would require:
var w = Window.find ('palette', "Window 1");
if (w) {
w.close();
}
w = Window.find ('palette', "Window 2");
if (w) {
w.close();
}
// ...
w = Window.find ('palette', "Window 20");
if (w) {
w.close();
}
Is there a way to do:
var w = Window.find ('palette', "*"); // Any title ???
while (w) {
w.close();
}
I came up with a crude way to do it over the weekend before I read your reply. Each window has a Btn_Close on it which should be visible to any script, so if I named all the buttons Btn_Close, I could execute Btn_Close.onClick() and close the window - assuming I could verify Btn_Close was valid and I named all the buttons identically.
Copy link to clipboard
Copied
I'm not JS guy - but according to this:
https://www.indesignjs.de/extendscriptAPI/indesign-latest/#WindowSUI.html#d1e10891
Title can be an empty string - so maybe it will return list / array / collection / whatever of ALL user created Windows?
Copy link to clipboard
Copied
I think that would only close windows with no defined title and leave other windows open, but I didn't test.
Copy link to clipboard
Copied
Window.find (''); finds any window, but closing a window doesn't destroy it, so Window.find('') always finds the same window. There is no way to collect all windows and close them.
Copy link to clipboard
Copied
Just thinking out loud, but what about:
var w = Window.find ('palette', "");
while (w) {
w.close();
w=null;
}
Also - if I keep closing the any of the windows and opening the same ones, I guess I'd eventually have 20-30 windows in memory, but 28 of them closed, correct?
Copy link to clipboard
Copied
That code won't work, try it.
>if I keep closing the any of the windows and opening the same ones, I guess I'd eventually have 20-30 windows in memory, but 28 of them closed, correct?
I think so, yes.
Copy link to clipboard
Copied
It took me a while to get my head around this, but I figured it out now:
Thank you so much for your patience and guidance!
Copy link to clipboard
Copied
I'm having two new issues and hope you can help me with them:
***
Background:
***
Issues:
***
UPDATE: I did a test and found that if I change the DocB script and re-name Ckbx_SelectAll as CkBx_SelectAll_DocB througout, (and Ckbx_SingleSelect to Ckbx_SingleSelect_DocB) the issue is resolved (the first issue). So the questions now become:
Copy link to clipboard
Copied
Issue 1 sounds as if it's still a problem with variable scope. Maybe check you variable (non-)declarations again.
> do I need to go through each of the scripts and make sure ALL the butttons and checkboxes use unique names?
That might be a good idea. But you can target specific controls by looking for them in specifuc windows. Use .find() to find a window, then use find() to find a named contro, in the window.
But another way of organising variables is to use a variable for a window, then declare the window's controls not as autonomous variables but as properties of the window. Something along these lines:
var w1 = new Window ("palette", "Window 1");
w1.btn = w.add ("button", undefined, "OK");
w1.ckbx = w.add("checkbox", undefined,"Check Box");
w1.add ("button", undefined, "Cancel");
w1.btn.onClick=function(){
alert("You clicked OK on Window 1");
}
w1.show();
You can the define your second window simply by copying w1 and replacing w1 with w2.
The advantage of this approach is that you won't run into problems of variable scope and ambiguity.
Copy link to clipboard
Copied
@Peter Kahrel - Great answer. Basically, there was a lot of rework b/c I didn't know what I was doing (nothing new).
Looks like there three solutions - each with a fair amount of re-work since I didn't plan for them initially:
If I ever do another major project in scripting, I think I'll use your third method!!!
Copy link to clipboard
Copied
Another newbie mistake for others to learn from:
As @Peter Kahrel said, if you name your window w1, you can simply copy it and rename it as w2. The same would work for win1 or win2.
If you name it "win" or "w", you can't do this b/c you have lines like "var Win = new Window" which then becomes "var Win2 = new Win2dow" and won't compile.
You can figure out how I know this ...
Copy link to clipboard
Copied
But another way of organising variables is to use a variable for a window, then declare the window's controls not as autonomous variables but as properties of the window. Something along these lines: ...
The advantage of this approach is that you won't run into problems of variable scope and ambiguity.
By @Peter Kahrel
I have a follow-up question to this. Let's say I add a panel named Pnl1 to the window and add the check box to the panel.
For only one window, the ckbx works whether I name it "ckbx", "w1.ckbx", or "w1.pnl1.ckbx."
So my question is: Am I really adding the controls as properties of the window, or am I just using the window as part of the name of the control, and I avoid ambiguity b/c the windows are named w1, w2?
I know it's a subtle distinction ...
Copy link to clipboard
Copied
They're properties. w = new Window(. . .) creates an object w, and w.ckbx = . . . creates an object as a property ckbx in w.
w1.ckbx and w2.ckbx are two distinct objects.
Copy link to clipboard
Copied
@Peter Kahrel - So specifically, if I added my checkbox to a panel on w1, then w1.pnl1.ckbx1 would would an object and non-ambiguous, but w1.ckbx1 would just be a name and thus bascially a "global variable", although that wouldn't create any issues unless I had two scritpts (or two functions in the same script) that both ran concurrently and both create a w1 with a pnl1 with a chbk1 (which would also create an issue for the properties method.)
Or am I misinterpreting it again?
Copy link to clipboard
Copied
I'm afraid you are (misinterpreting). w1.pnl1.ckbx and w1.ckbx are similar in nature, the only difference is that in w1.pnl1.ckbx, ckbx is embedded one level deeper.
Copy link to clipboard
Copied
@Peter Kahrel - I think my example was unclear. The chkbox is on the panel in both cases. Consider these two code examples:
var w1 = new Window ("palette", "Window 1");
w1.pnl1 = w.add ("Panel);
w1.pnl1.ckbx1 = w1.pnl1.add("checkbox", undefined,"Check Box");
or
var w1 = new Window ("palette", "Window 1");
w1.pnl1 = w.add ("Panel);
w1.ckbx1 = w1.pnl1.add("checkbox", undefined,"Check Box");
Both the codes work.
If I understand correctly, w1.pnl1.chbx1 is a property, whereas w1.ckbx1 is just a global variable with undefined scope and thus global.
However:
Is anything above incorrect?
Copy link to clipboard
Copied
In both code samples you have one variable, instantiated to a window, w1.
w1.ckbx1 is not a variable (global or otherwise), it's a property of window w1. Just like w1.pnl1.ckbx1: pnl1 is a property of window w1, and w1.pnl1.ckbx1 is a property of panel pnl1.
> if I happened to have two different windows named w1
Always a recipe for trouble!
Find more inspiration, events, and resources on the new Adobe Community
Explore Now