Skip to main content
Participant
November 6, 2013
Answered

[JS][CS5.5] Interrupting a script via ScriptUI

  • November 6, 2013
  • 2 replies
  • 3082 views

I have a script that automates the placement of PDFs onto pages based on an input XML file. It works splendidly, but I would like users to be able to interrupt the placement, particularly if they have accidentally passed the wrong XML file to the script!

Since the total time taken for the PDF placements can be a while, I put up a simple palette window containing a progress bar to give an idea of progress. I also added a cancel button, but although the window appears to have focus at least some of the time during the placements, it never becomes possible to press the cancel button, nor to close the window. The mouse pointer is an hourglass the whole time.

Below is a simplified test script that demonstrates the problem. I've only run it on CS5.5 on Windows XP, but I believe it should work at least as far back as CS4 on Mac and Windows. It asks for a PDF file and then places it in a new document 16 times. My PC is slow enough that it takes enough time overall to give me plenty of time to hit the cancel button, if it were possible to do so. If your machine is really fast, you might want to increase gridSize so that the script has more to do.

Is there anything I can do such that my cancel button can be pressed? I don't need to see the PDF import window, so if that can and needs to be turned off, that's fine. I dabbled with chains of IdleTasks, and was able to press my cancel button, but the chain didn't always end, and I ended up locking things up nastily. I probably need to read up more on IdleTasks. There may be potential there, but I would like to support earlier than CS5 if possible, and IdleTasks were introduced in CS5.

#target indesign

(function() {

    var gridSize = 4;

    // Ask user for a PDF

    var pdfFilter =($.os.toLowerCase().indexOf("macintosh") != -1) ?

        (function(file) { return file.name.match(/\.pdf$/); }) : '*.pdf';

    var pdfFile = File.openDialog("Choose a small PDF to place...", pdfFilter);

    if (!pdfFile) { return; }

    // Show a simple progress bar

    var active = true;

    var win = new Window('palette', 'Placing ' + pdfFile.name);

    var label = win.add('statictext', undefined, '');

    label.preferredSize.width = 300;

    label.justify = 'left';

    var progressBar = win.add('progressbar', undefined, 0, gridSize * gridSize);

    progressBar.preferredSize = [ 300, 12 ];

    var cancelButton = win.add('button', undefined, 'Cancel');

    cancelButton.onClick = function() { win.close(); };

    win.onClose = function() { active = false; };

    win.show();

    // Make a grid of rectangles and place the PDF in each rectangle,

    // advancing the progress bar as we go

    var doc = app.documents.add();

    var page = doc.pages[0];

    var mp = page.marginPreferences;

    var originX = page.bounds[1] + mp.left;

    var originY = page.bounds[0] + mp.top;

    var rectWidth = (page.bounds[3] - mp.right - originX) / gridSize;

    var rectDepth = (page.bounds[2] - mp.bottom - originY) / gridSize;

    var placePDF = function(n) {

        var y = Math.floor(n / gridSize);

        var x = n % gridSize;

        label.text = 'Placing PDF in [ ' + x + ', ' + y + ' ]';

        var rect = page.rectangles.add();

        rect.geometricBounds = [

            originY + y * rectDepth,

            originX + x * rectWidth,

            originY + (y + 1) * rectDepth,

            originX + (x + 1) * rectWidth

        ];

        rect.strokeWeight = 0;

        var pdfList = rect.place(pdfFile);

        pdfList[0].fit(FitOptions.PROPORTIONALLY);

        (progressBar.value)++;

        // Even this sleep doesn't let me press the cancel button!

        //$.sleep(1000);

    }

    for (var i = 0; active && i < gridSize*gridSize; i++) {

        placePDF(i);

    }

    win.close();

})();

This topic has been closed for replies.
Correct answer Marc Autret

Hi Ariel,

Yet another example of SUI that doesn't work on CC

Can't use w.addEventListener

As far as I know the only thing on CC one can add an eventListener on the SUI is an Image.

On everything else it's all onClick etc.

Pathetic to say the least (CC not your script!)

Trevor


Hi all,

To my knowledge ScriptUI can only process 'update' events while your heavy routine is running. As a workaround Roey Horns from Adobe suggested in the past that we "rely on InDesign's support for canceling scripts with the Esc key or Cmd-Period".

Anyway, IdleTasks is definitely the way to go in CS5 and later.

@+

Marc

2 replies

TᴀW
Legend
November 6, 2013

Also, this business of stopping the script by setting active to false --

I guess there's no reason that shouldn't work in theory, but I wonder if

for some reason it just doesn't. Have you tried a simple alert() in the

onClick function, just to see if maybe the onClick is registering, but

the active=false business isn't?

id-extras.com | InDesign tools & scripts for typesetters, form designers, and translators
TᴀW
Legend
November 6, 2013

Have you tried:

(a) using addEventListener() instead of the built-in onClick to the

button? Perhaps addEventListener is more sensitive?

(b) perhaps try using addEventListener to the Window object instead of

the button and seeing if that is more "sensitive" to events. (You could

then of course test to see if it was the button that was clicked.)

?

Just suggestions... haven't tried them myself.

Ariel

id-extras.com | InDesign tools & scripts for typesetters, form designers, and translators
XarquolAuthor
Participant
November 6, 2013

Sadly, neither of your suggestions in reply 1 appear to make any difference.

Out of interest though, how would I additionally test that the button had been clicked if the Window held the event listener, rather than the button?

In regards to reply 2, an extra alert does not show itself either. If the onClick was being acted upon, my window would close. It is only when the window closes that the "active" boolean is set to false to terminate the placement loop, but my window remains open no matter how often I click.

I think the trouble is really that I'm expecting multi-threaded behaviour (one thread for the placement loop, one to look after the gui and process clicks) when in reality there is only one thread, and it's busy placing PDFs. I wonder though if there is some pseudo-way to carve up the single thread and get it to check GUI state often enough to get what I want. As I said earlier, using IdleTasks sort of works in principle, but can get a little out of control!

TᴀW
Legend
November 6, 2013

Like this:

w = new Window("dialog");

b = w.add("button", undefined, "Hello");

w.addEventListener("mouseup", myEvent);

w.show();

function myEvent(e){

alert(e.target);

}

Ariel

PS Sorry that it's not all carefully wrapped up in anonymous functions

and local variables like yours

id-extras.com | InDesign tools & scripts for typesetters, form designers, and translators