Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Script Up - Close other palettes before opening new palette

Enthusiast ,
May 15, 2025 May 15, 2025

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:

  • ckbx1 seems to be "global" - i.e. I don't have to pass it as an argument to ShowWindow2.
  • w and btn1 do not appear to be global - the script interprets them correctly, even though they have identical names?
  • w.close gives me an error, even though w should already be defined as window 1.

 

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.

TOPICS
Scripting
1.9K
Translate
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

correct answers 2 Correct answers

Community Expert , May 16, 2025 May 16, 2025

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();
}
Translate
Community Expert , Jun 12, 2025 Jun 12, 2025

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

...
Translate
Community Expert ,
May 15, 2025 May 15, 2025

> 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.

Translate
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 ,
May 15, 2025 May 15, 2025

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.)

 

Translate
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
LEGEND ,
May 15, 2025 May 15, 2025

@Marshall_Brooks

 

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. 

 

Translate
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
Community Expert ,
May 16, 2025 May 16, 2025

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();
}
Translate
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
Community Expert ,
May 15, 2025 May 15, 2025

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();

    }

})();
Translate
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
Community Expert ,
May 16, 2025 May 16, 2025

[removed]

Translate
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
Community Expert ,
May 16, 2025 May 16, 2025

@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.

Translate
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 ,
May 19, 2025 May 19, 2025

@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.

Translate
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
LEGEND ,
May 19, 2025 May 19, 2025

@Marshall_Brooks

 

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? 

 

Translate
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 ,
May 19, 2025 May 19, 2025

I think that would only close windows with no defined title and leave other windows open, but I didn't test.

Translate
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
Community Expert ,
May 19, 2025 May 19, 2025

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.

Translate
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 ,
May 19, 2025 May 19, 2025

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?

Translate
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
Community Expert ,
May 19, 2025 May 19, 2025

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.

Translate
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 ,
May 20, 2025 May 20, 2025

It took me a while to get my head around this, but I figured it out now:

  • From @Peter Kahrel guide (Page 77), there is not way to get rid of a palette window, once opened, other than closing the target engine (FrameMaker, in my case).
  • If you have more than one window with the same name open, you won't be able to close the active window. Window.find will find one of the closed ones and close it again, so the open one will never be affected.
  • I had to re-write my code to only open one window (again - Page 77 of the guide). Some tips for this:
    • Originally (probably per the Adobe Javascript Tool Guide CS6.pdf file), I was setting up the window, initializing the buttons, and then showing the window. I found it easier to keep track of if I moved the win.show() command immediately after the last control is added to the window, and moving the button initialization steps after the win.show() command.
    • I found I had to account for both conditions when I did this. For example, let's say I have a checkbox to turn on or off automatic change bars and show the current state. With the original method, I only had to change the checkbox to "true" if they were enabled - the checkbox is "false" by default. WIth the new method, I had to set the checkbox to "true" if enabled or "false" if disabled. (The checkbox could have been in either state when the pallette was last closed.)

Thank you so much for your patience and guidance!

Translate
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 ,
Jun 11, 2025 Jun 11, 2025

I'm having two new issues and hope you can help me with them:

***

Background:

  • I am using this with FrameMaker, but it is esssentially a ScriptUI question.
  • As I now understand it, palette windows remain open until I exit FrameMaker, they can be hidden, but they still exist in memory.
  • Many of my windows use the same names for buttons/controls, which doesn't seem (read on) to cause any issues.
  • We have about 10 document templates.
  • I created essentially two palette dialogs for each template. One turns on and off conditional text (among other features) and one updates variables. The scripts are revised as above to only create one window - if it doesn't exist, it creates it. If it does exist, it re-opens it.
  • I have a separate script that checks for any of the windows and closes the window if it is open, then reads a variable in the document and opens the correct conditional text palette.
  • Each conditional text palette has a panel with checkboxes. These panels have a button labelled "Select All" and "Single Select." Neither of these are radio buttons, but they act like it - i.e. if I click "Select All", it deselects "Single Select" and either selects or deselects all the other buttons in the panel. If I click SingleSelect, it deselects SelectAll and each button acts like a radio button.

***
Issues:

  • I open DocA and the ShowConditonal text window works fine and the Select All and Single Select buttons work fine. I open DocB and the ShowCondiitional Text Window for DocB works fine and the Select All and Single Select buttons work fine. I switch back to DocA and re-open the ShowConditional Text window and the Select All and Single Select buttons no longer work. I can click Select All and nothing changes, I click Single Select and everything is deselected, but SelectAll remains Selected. Closing and re-opening the pallete doesn't resolve the issue. Essentially it doesn't work again until I close and re-open FrameMaker. DocB still works correctly. (If I swap the order, it swaps, i.e. if I open DocB first and then open DocA, DocB stops working, but DocA still works).
  • Issue2: Less common, but the scripts check the active document - i.e. if I am working on a DocA template document and have the DocB show Conditional text window open, the script should pop-up "The active document is not using the Doc B template" and does not perform the action. Sometimes, I will be working on DocA, have the DocA Show Conditional text window open, and will still get the "Active Document is not using Doc B" message. This seems to only happen when I have opened several different documents in FrameMaker. Again, closing FM and re-opening it seems to be the only way to get things working properly again.

***

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:

  • Why was this required for these checkboxes?
  • Ideally, do I need to go through each of the scripts and make sure ALL the butttons and checkboxes use unique names?
Translate
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
Community Expert ,
Jun 12, 2025 Jun 12, 2025

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.

Translate
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 ,
Jun 12, 2025 Jun 12, 2025

@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:

  • Before you replied (and I'm almost finished), I renamed all the controls to the window. So the DocA window will have Ckbx_someproperty_DocA as the name. _DocB for the DocB window.
  • The dual find commands seem a bit cumbersome.
  • Ironically, I saw the last approach in the Adobe Javascript CS6 examples, but it didn't explain that it was making it a property of the window. And I didn't understand that they weren't just names. So they had examples like Win1.Panel1.Text1 (Which probably could have been Win1.txt_DocNum, if I wanted). I did that with the first window, but it was hard to code (remembering that Text1 was the DocNum field), and then I didn't know any better so I named the second window Win1 also. (But I didn't have issues then b/c I was always creating new windows each time the script ran, so I might have had 10 or 15 windows closed and hiding in memory.)

If I ever do another major project in scripting, I think I'll use your third method!!!

Translate
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 ,
Jun 12, 2025 Jun 12, 2025

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 ...

Translate
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 ,
Jun 18, 2025 Jun 18, 2025
 
quote

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

@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 ...

Translate
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
Community Expert ,
Jun 18, 2025 Jun 18, 2025

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.

Translate
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 ,
Jun 19, 2025 Jun 19, 2025

@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?

 

Translate
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
Community Expert ,
Jun 19, 2025 Jun 19, 2025

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.

 

 

Translate
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 ,
Jun 19, 2025 Jun 19, 2025

@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:

  • w1.pnl1.Ckbx1, even though it's a property could still give me potential issues, if I happened to have two different windows named w1 with a pnl1 with a Ckbx1 in different scripts (I think).
  • w1.Ckbx1 would give me potential issues if I had that same "variable" anywhere in the script, even if I just mistyped and add w1.Ckbx1 to w2 with no panel - however, as long as I used unique window and variable names, it wouldn't be an issue.

Is anything above incorrect?

 

Translate
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
Community Expert ,
Jun 19, 2025 Jun 19, 2025

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!

 

 

Translate
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