Skip to main content
Inspiring
May 15, 2025
Answered

Script Up - Close other palettes before opening new palette

  • May 15, 2025
  • 3 replies
  • 2294 views

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/15286930#M622092

 

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.

Correct answer Peter Kahrel

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?

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.

3 replies

Peter Kahrel
Community Expert
Community Expert
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.

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

Robert at ID-Tasker
Legend
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? 

 

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

    }

})();
Peter Kahrel
Community Expert
Community Expert
May 16, 2025

[removed]

Peter Kahrel
Community Expert
Community Expert
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.

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

 

Robert at ID-Tasker
Legend
May 16, 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.