Copy link to clipboard
Copied
I found this thread: https://community.adobe.com/t5/illustrator-discussions/auto-close-alert-message/td-p/9398258
Images here: https://github.com/Marshall-Brooks/Sandbox/issues/2
See also:
I'm somewhat spoiled by the Enhanced Message Box add-on for Microsoft Access which shows a standard Msgbox with a countdown of seconds until the box closes.
I used @Peter Kahrel's Scipt UI guide to modify the first linked script as follows:
function AutocloseAlert(message, delaySeconds, title){
title = title || 'Alert';
var alertWindow = new Window('palette', title);
// var control_text = alertWindow.add('edittext', [0, 0, 500, 200], message, {multiline: true});
// var control_text = alertWindow.add('edittext', , message, {multiline: true});
var control_text = alertWindow.add('edittext', undefined, message, {multline:true})
// if(delaySeconds === 0){
var control_close = alertWindow.add('button', undefined, 'OK');
control_close.onClick = function(){
if(alertWindow){
alertWindow.hide();
alertWindow = null;
}
};
// }
alertWindow.show();
alertWindow.update();
if(delaySeconds > 0){
$.sleep(delaySeconds * 1000);
alertWindow.hide();
alertWindow = null;
}
}
I'm having the following issues:
var startTime = new Date().getTime();
while ( new Date().getTime() - startTime < delaySeconds * 1000 ) {alertWindow.update()}
But it didn't change how it worked - i.e. the window was still grayed out, and clicking the OK button did not close the window, but it did disappear after the delaySeconds interval.
Thank you in advance!!!
Eh that didn't work - is this what you're thinking of ?
This works for me
function CountdownAlert(message, delaySeconds, title) {
title = title || "Countdown Alert";
var win = new Window("palette", title);
win.orientation = "column";
win.alignChildren = "center";
var msg = win.add("statictext", undefined, message);
var btn = win.add("button", undefined, "OK (" + delaySeconds + ")");
var cancelled = false;
// Function for button click
btn.onClick = functio
...
Updated the scripts to auto-size and or wrap correctly with the help of this thread: https://community.adobe.com/t5/indesign-discussions/script-ui-dynamically-autosizing-statictext/td-p/15275567#M621971
EDIT: Had to make a minor change to the "if" statement in AutocloseAlert(). The previous version would fail (only display the first line) if message length was < 80 and you have manual line feeds, e.g.:
AutocloseAlert("Line 1\rLine2");
EDIT2: Had to correct the "if" statement, not found returns -1
...Copy link to clipboard
Copied
Try using Idle Task instead of sleep
function AutocloseAlert(message, delaySeconds, title) {
title = title || 'Alert';
delaySeconds = delaySeconds || 5;
var alertWindow = new Window('palette', title);
alertWindow.orientation = 'column';
alertWindow.alignChildren = 'fill';
var textBox = alertWindow.add('statictext', undefined, message, { multiline: true });
textBox.characters = 50;
var button = alertWindow.add('button', undefined, 'OK (' + delaySeconds + ')');
var countdown = delaySeconds;
var idleTask;
// Button closes early
button.onClick = function () {
if (idleTask && idleTask.isValid) {
idleTask.remove();
}
alertWindow.close();
};
// This function will be called repeatedly by IdleTask
function onIdleEvent() {
countdown--;
if (!button || !button.text) return;
if (countdown <= 0) {
if (idleTask && idleTask.isValid) {
idleTask.remove();
}
alertWindow.close();
} else {
button.text = 'OK (' + countdown + ')';
}
}
// Create IdleTask
idleTask = app.idleTasks.add({ name: "AutocloseAlertTimer", sleep: 1000 });
// Attach event listener
idleTask.addEventListener(IdleEvent.ON_IDLE, function () {
onIdleEvent();
});
alertWindow.show();
}
Copy link to clipboard
Copied
Eh that didn't work - is this what you're thinking of ?
This works for me
function CountdownAlert(message, delaySeconds, title) {
title = title || "Countdown Alert";
var win = new Window("palette", title);
win.orientation = "column";
win.alignChildren = "center";
var msg = win.add("statictext", undefined, message);
var btn = win.add("button", undefined, "OK (" + delaySeconds + ")");
var cancelled = false;
// Function for button click
btn.onClick = function () {
cancelled = true;
win.close();
$.writeln("User clicked OK");
};
// Show the window
win.show();
// Countdown loop
while (delaySeconds > 0 && !cancelled) {
$.sleep(1000); // wait 1 second
delaySeconds--;
try {
btn.text = "OK (" + delaySeconds + ")";
win.update(); // Force the window to update
} catch (e) {
break; // window might be closed already
}
}
// Close window after countdown, unless user clicked OK
if (!cancelled) {
win.close();
$.writeln("Auto-closed after timeout");
}
}
// Example usage: countdown from 5 seconds
CountdownAlert("This message will close in 5 seconds.", 5, "Autoclose Alert");
Copy link to clipboard
Copied
@Eugene Tyson - I didn't understand your code, although it looks really good, but I am getting an error "Undefined is not an object" on the line idleTask = app.itleTasks.add({name:"AutocloseAlertTimer", sleep: 1000})
I should have added - my script is being run in FrameMaker, but I was told the InDesign forum had better ScriptUI support.
Copy link to clipboard
Copied
@Eugene Tyson Second script is almost perfect. Only issue is I can't click on the OK button - well I can, but nothing happens. I would like the alert to count down the time remaining, but be able to close early if desired.
Much better than what I started with, though!!!
Copy link to clipboard
Copied
I'm only learning scripting so this is cobbled together from bits of other scripts I have.
I think I'd need a broader context to what you're doing to fully do what you want.
Let me see if I can fix the OK button.
But more details on your overall goal will help me greatly understand.
Copy link to clipboard
Copied
@Eugene Tyson - What you have is great! I made two minor changes. I changed:
btn.text = "OK (" + delaySeconds + ")";
win.update(); // Force the window to update
To:
if(delaySeconds > 0){
btn.text = "OK (" + delaySeconds + ")";
}
else {
btn.text = "OK";
}
//win.update(); // Force the window to update
It looked odd having the countdown show "OK (0)" and the window still displayed, and the text would flicker once a second with win.update(), and the script works with it commented out.
Just need the OK button to work.
Broader context: I have a larger script that takes about 1-2 seconds to run in the office, but 6-7 seconds to run at home over VPN. 6-7 seconds is long enough that you aren't certain if the script has completeted or not, but 1-2 seconds is annoying to have to mouse over and click OK before you can continue. So I want to pop-up a msg for a couple of seconds that the script is complete, but then you don't have to click OK to close the message.
UPDATE: I was originally using something similar in an MS Access Database with VBA where I have a long script that runs in the background and I wanted a pop-up to show that the script was complete, but if the script were run unattended, it wouldn't wait for two hours until the user returned from lunch. There would be similar use cases for ScriptUI, but that isn't personally what I need it for (yet ...)
Copy link to clipboard
Copied
@Eugene Tyson - Found another really minor error with your script. It doesn't work with delaySeconds = 0.
Normally, I wouldn't care, but I figured out I could use SetFont (Page 79 of @Peter Kahrel 's guide: https://creativepro.com/files/kahrel/indesign/scriptui.html) with your script and have the script readable. I was going to replace all my alert functions with yours, but I can use the earlier script I posted if I don't need a delay.
Disregard above: I can put an "If" (if(delaySeconds)>0){ } around the countdown loop portion of your code and it works fine (And change the button text code).
Copy link to clipboard
Copied
No prob glad its a starting point. Will jump back in tomorrow if you still need help
Copy link to clipboard
Copied
Thanks again. I still need to have the OK button functional if there is a delaySeconds value. For present use, I don't HAVE to have it, but I don't think I'll figure it out on my own.
Copy link to clipboard
Copied
Yeh so can't get the button to work - but can press ESC on the keyboard not sure if that's quitting the dialog only or ending the script ...
But if that works then you don't need a button.
$.sleep() freezes the UI, so the button never gets a chance to register clicks during that time.
I'm trying with idletask - but can't get anywhere - seems like it's single threaded so when it's doing the countdown it can't do anything else like click a button.
Copy link to clipboard
Copied
@Eugene Tyson - Stand down, please (and tremendous thanks!!!)!
The okay button is working for me today. Not sure why - it wasn't yesterday and it didn't seem to be for you.
Your comments got my curious, so I did some testing with this:
AutocloseAlert("This message will close in 10 seconds. Checking for a really long message. Not that it matters.", 10, "Autoclose Alert");
alert("done");
Keyboard Esc did NOT do anything for the script, however, clicking the red X closed the window, but left the script running and didn't display the "done" alert until the timer expired. (Keyboard Enter didn't work either, which is the default for clicking OK in Access VBA, but I'm not going to worry about that.)
And I need the button to display the countdown timer.
If it couldn't be fixed, I might take OK off the button, but my team is used to seeing it from Access. More likely I would just set the timer to a really low value like two seconds, and if someone happened to be quick enough to get the mouse over to it, they would just think they had to click it twice for some reason.
Latest version of the code in following reply, in case something I added fixed the issue.
Copy link to clipboard
Copied
Full Script:
function set_font (control, font) {
for (var i = 0; i < control.children.length; i++) {
if ("GroupPanel".indexOf (control.children[i].constructor.name) > -1)
set_font (control.children[i], font);
else
control.children[i].graphics.font = font;
}
}//--end set_font;
function AutocloseAlert(message, delaySeconds, title) {
title = title || "Script Alert";
var win = new Window("palette", title, undefined, {closeButton:false});
win.orientation = "column";
win.alignChildren = "center";
// win.graphics.backgroundColor = win.graphics.newBrush (win.graphics.BrushType.SOLID_COLOR, [1.0, 1.0, 1.0]);
var msg = win.add("statictext", undefined, message);
// msg.graphics.backgroundColor = msg.graphics.newBrush (msg.graphics.BrushType.SOLID_COLOR, [1.0, 1.0, 1.0]);
if (delaySeconds>0){
var btn = win.add("button", undefined, "OK (" + delaySeconds + ")");
}
else{
var btn = win.add("button", undefined, "OK");
}
var cancelled = false;
// Function for button click
btn.onClick = function () {
cancelled = true;
win.close();
$.writeln("User clicked OK");
};
// Show the window
set_font (win, "Tahoma:14");
win.show();
if (delaySeconds>0){
// Countdown loop
while (delaySeconds > 0 && !cancelled) {
$.sleep(1000); // wait 1 second
delaySeconds--;
try {
if(delaySeconds > 0){
btn.text = "OK (" + delaySeconds + ")";
}
else {
btn.text = "OK";
}
//win.update(); // Force the window to update
} catch (e) {
break; // window might be closed already
}
}
// Close window after countdown, unless user clicked OK
if (!cancelled) {
win.close();
$.writeln("Auto-closed after timeout");
}
}
} // End AutocloseAlert
Copy link to clipboard
Copied
@Eugene Tyson - Just so you know I'm not going crazy and in case it is helpful to you:
If I launch the script from ESTK and target ExtendScript Toolkit CC, the OK button works flawlessly. If I target FrameMaker 2022, the OK button cannot be clicked.
Not sure if that helps you or not, but I'm not going to worry too much over it. I'll just set the delay to something short like two seconds.
(Some of the team interpret it as they can't do anythiing until the timer runs down, so that works just as well anyway ...)
Copy link to clipboard
Copied
Not sure if this helps: https://stackoverflow.com/questions/31439286/does-javascript-have-anything-similar-to-vbas-doevents Your mention of single-threaded made me think of DoEvents in VBA, so I was wondering if there was something similar, but the SO page is pure javascript and mentions web browsers, so might not work with ExtendScript/ScriptUI.
Copy link to clipboard
Copied
EDIT: Removed the second commented graphics line.
Another minor update - the script was not pausing if DelaySeconds was zero. I needed to change it from a pallette to a dialog:
function set_font (control, font) {
for (var i = 0; i < control.children.length; i++) {
if ("GroupPanel".indexOf (control.children[i].constructor.name) > -1)
set_font (control.children[i], font);
else
control.children[i].graphics.font = font;
}
}//--end set_font;
function AutocloseAlert(message, delaySeconds, title) {
title = title || "Script Alert";
if(delaySeconds===0){
var win = new Window("dialog", title, undefined, {closeButton:false});
}
else{
var win = new Window("palette", title, undefined, {closeButton:false});
}
win.orientation = "column";
win.alignChildren = "center";
// win.graphics.backgroundColor = win.graphics.newBrush (win.graphics.BrushType.SOLID_COLOR, [1.0, 1.0, 1.0]);
var msg = win.add("statictext", undefined, message);
if (delaySeconds>0){
var btn = win.add("button", undefined, "OK (" + delaySeconds + ")");
}
else{
var btn = win.add("button", undefined, "OK",{name: "ok"});
}
var cancelled = false;
// Function for button click
btn.onClick = function () {
cancelled = true;
win.close();
$.writeln("User clicked OK");
};
// Show the window
set_font (win, "Tahoma:14");
win.show();
if (delaySeconds>0){
// Countdown loop
while (delaySeconds > 0 && !cancelled) {
$.sleep(1000); // wait 1 second
delaySeconds--;
try {
if(delaySeconds > 0){
btn.text = "OK (" + delaySeconds + ")";
}
else {
btn.text = "OK";
}
//win.update(); // Force the window to update
} catch (e) {
break; // window might be closed already
}
}
// Close window after countdown, unless user clicked OK
if (!cancelled) {
win.close();
$.writeln("Auto-closed after timeout");
}
}
} // End AutocloseAlert
Copy link to clipboard
Copied
Wanted to clarify also - the commented line beginning win.graphics.background color changes the background of the pop-up from gray to white.
Our team (mainly myself) debated this a bit.
Ultimately we (I) decided to leave it with gray, but it would also be simple to pass an additional parameter to the script (Like is done with the title) and have it selectable based on the intent of the message.
Copy link to clipboard
Copied
Minor change to the script above.
If delaySeconds = 0, I added {name: "ok"} to the line that adds the OK button. This allows you to press the Kbd Enter key to close the message. (Even though since the button's text is "OK" that should work anyway, but it doesn't seem to.)
I intentionally did NOT add it if delaySeconds > 0 b/c it seems to work like the red X did, i.e. if you press the Kbd enter, the pop-up closes after a few seconds, but the script still doesn't continue until the delay expires.
Copy link to clipboard
Copied
Back again - minor changes to the script. I made delaySeconds default to 0. This way you can use the script exactly the same as the alert() function, except the text will use the custom font. And a added a parameter for the bgcolor, but if you don't pass it a color, it uses gray:
function AutocloseAlert(message, delaySeconds, title, bgcolor) {
title = title || "Script Alert";
delaySeconds = delaySeconds || 0
bgcolor = bgcolor || "gray";
if(delaySeconds===0){
var win = new Window("dialog", title, undefined, {closeButton:false});
}
else{
var win = new Window("palette", title, undefined, {closeButton:false});
}
win.orientation = "column";
win.alignChildren = "center";
if(bgcolor==="white"){
win.graphics.backgroundColor = win.graphics.newBrush (win.graphics.BrushType.SOLID_COLOR, [1.0, 1.0, 1.0]);
}
var msg = win.add("statictext", undefined, message);
if (delaySeconds>0){
var btn = win.add("button", undefined, "OK (" + delaySeconds + ")");
}
else{
var btn = win.add("button", undefined, "OK",{name: "ok"});
}
var cancelled = false;
// Function for button click
btn.onClick = function () {
cancelled = true;
win.close();
$.writeln("User clicked OK");
};
// Show the window
set_font (win, "Tahoma:14");
win.show();
if (delaySeconds>0){
// Countdown loop
while (delaySeconds > 0 && !cancelled) {
$.sleep(1000); // wait 1 second
delaySeconds--;
try {
if(delaySeconds > 0){
btn.text = "OK (" + delaySeconds + ")";
}
else {
btn.text = "OK";
}
//win.update(); // Force the window to update
} catch (e) {
break; // window might be closed already
}
}
// Close window after countdown, unless user clicked OK
if (!cancelled) {
win.close();
$.writeln("Auto-closed after timeout");
}
}
} // End AutocloseAlert
@Eugene Tyson New issue: I wanted something like the Enhanced Message Box for Access (but not quite as fancy (without custom button colors, delay before buttons are enabled, etc.): https://datenbank-projekt.de/projekte/improved-enhanced-message-box-ms-access
Script UI has the Confirm() function (which uses Yes/No, even though Javascript Confirm uses OK/Cancel), but this doesn't work if, for example, you wanted Abort/Retry/Ignore. I came up with the following with 4 possible buttons:
function CustomConfirm(message, title, DefaultBtn, Btn1Text, Btn2Text, Btn3Text, Btn4Text, bgcolor) {
// Yes/No, OKOnly, OK/Cancel, Abort/Retry/Ignore, Yes/No/Cancel, Retry/Ignore,
title = title || "Script Alert";
Btn1Text = Btn1Text || "OK";
Btn2Text = Btn2Text || "";
Btn3Text = Btn3Text || "";
Btn4Text = Btn4Text || "";
DefaulBtn = DefaultBtn || 0;
bgcolor = bgcolor || "gray";
var result = "";
var win = new Window("dialog", title, undefined, {closeButton:false});
win.orientation = "column";
win.alignChildren = "left";
if(bgcolor==="white"){
win.graphics.backgroundColor = win.graphics.newBrush (win.graphics.BrushType.SOLID_COLOR, [1.0, 1.0, 1.0]);
}
var msg = win.add("statictext", undefined, message);
var myButtonGroup = win.add ("group");
myButtonGroup.alignment = "center";
var Btn1 = myButtonGroup.add ("button", undefined, Btn1Text);
if(Btn2Text!==""){
var Btn2 = myButtonGroup.add ("button", undefined, Btn2Text);
}
if(Btn3Text!==""){
var Btn3 = myButtonGroup.add ("button", undefined, Btn3Text);
}
if(Btn4Text!==""){
var Btn4 = myButtonGroup.add ("button", undefined, Btn4Text);
}
switch(DefaultBtn){
case 1:
win.defaultElement=Btn1;
break;
case 2:
win.defaultElement=Btn2;
break;
case 3:
win.defaultElement=Btn3;
break;
case 4:
win.defaultElement=Btn4;
break;
}
// Event Listeners
Btn1.onClick=function(){
// alert(Btn1Text);
result = Btn1Text;
//alert(result);
// return result;
win.close();
$.writeln("User clicked Abort");
$.writeln(Btn1Text);
return result;
};
Btn2.onClick=function(){
result = Btn2Text;
win.close();
$.writeln("User clicked Retry");
$.writeln(Btn2Text);
return result;
};
Btn3.onClick=function(){
result = Btn3Text;
win.close();
$.writeln("User clicked Ignore");
$.writeln(Btn3Text);
return result;
};
Btn4.onClick=function(){
result = Btn4Text;
win.close();
$.writeln("User clicked Retry");
$.writeln(Btn4Text);
return result;
};
// Show the window
set_font (win, "Tahoma:14");
win.show();
} // End CustomConfirm
// Usage
switch(CustomConfirm("Select A Button", undefined, 2, "Abort", "Retry", "Ignore")){
Case "Abort"
alert("You selected Abort")
break;
Case "Retry"
alert("You selected Retry")
break;
Case "Ignore"
alert("You selected Ignore")
break;
}
The script sets up the window properly and looks fine, but it returns "undefined" instead of the button text, and I don't know why - which makes it pretty much useless. The commented out alert buttons work and display the correct results, so I'm not sure why the return statement is not working.
(I'm also open to suggestions on the position of the title statement. You can't specify a title for the confirm statement. The way I have it, you have to specify "undefined" for the second position. If I move it to the end, you could ignore it, but then for a simple Yes/No pop-up with a custom button, you would have to specify "CustomConfirm("Select a button", 2, "Yes", "No", undefined, undefined, "Button Selection:")"
Copy link to clipboard
Copied
New problems:
Copy link to clipboard
Copied
Have the script working, the problem was in the calling procedure. Here's the sloppy script with commented lines still included:
function CustomConfirm(message, title, DefaultBtn, Btn1Text, Btn2Text, Btn3Text, Btn4Text, bgcolor) {
// Yes/No, OKOnly, OK/Cancel, Abort/Retry/Ignore, Yes/No/Cancel, Retry/Ignore,
title = title || "Script Alert";
Btn1Text = Btn1Text || "";
Btn2Text = Btn2Text || "";
Btn3Text = Btn3Text || "";
Btn4Text = Btn4Text || "";
DefaulBtn = DefaultBtn || 0;
bgcolor = bgcolor || "gray";
var mainresult = "";
var win = new Window("dialog", title, undefined, {closeButton:false});
win.orientation = "column";
win.alignChildren = "left";
if(bgcolor==="white"){
win.graphics.backgroundColor = win.graphics.newBrush (win.graphics.BrushType.SOLID_COLOR, [1.0, 1.0, 1.0]);
}
var msg = win.add("statictext", undefined, message);
var myButtonGroup = win.add ("group");
myButtonGroup.alignment = "center";
var Btn1 = myButtonGroup.add ("button", undefined, Btn1Text);
if(Btn1Text===""){
Btn1.visible=false;
}
// if(Btn2Text!==""){
var Btn2 = myButtonGroup.add ("button", undefined, Btn2Text);
if(Btn2Text===""){
Btn2.visible=false;
}
// }
// if(Btn3Text!==""){
var Btn3 = myButtonGroup.add ("button", undefined, Btn3Text);
if(Btn3Text===""){
Btn3.visible=false;
}
// }
// if(Btn4Text!==""){
var Btn4 = myButtonGroup.add ("button", undefined, Btn4Text);
if(Btn4Text===""){
Btn4.visible=false;
}
// }
switch(DefaultBtn){
case 1:
win.defaultElement=Btn1;
break;
case 2:
win.defaultElement=Btn2;
break;
case 3:
win.defaultElement=Btn3;
break;
case 4:
win.defaultElement=Btn4;
break;
}
//alert(Btn4.ObjectValid())
// Event Listeners
Btn1.onClick=function(){
// alert(Btn1Text);
result = Btn1Text;
//alert(result);
// return result;
win.close();
$.writeln("User clicked Abort");
$.writeln(Btn1Text);
return result;
};
Btn2.onClick=function(){
result = Btn2Text;
win.close();
$.writeln("User clicked Retry");
$.writeln(Btn2Text);
return result;
};
Btn3.onClick=function(){
result = Btn3Text;
win.close();
$.writeln("User clicked Ignore");
$.writeln(Btn3Text);
return result;
};
Btn4.onClick=function(){
result = Btn4Text;
win.close();
// $.writeln("User clicked Retry");
// $.writeln(Btn4Text);
return result;
}
// Show the window
set_font (win, "Tahoma:14");
win.show();
// alert(Btn1.onClick())
mainresult = result
// alert (mainresult)
$.writeln(mainresult);
return mainresult;
} // End CustomConfirm
Calling functions:
//alert(CustomConfirm("Select A Button:", undefined, 2, undefined, "Abort", "Retry", "Ignore"))
Returns what was selected ...
var answer = CustomConfirm("Select A Button:", undefined, 2, undefined, "Abort", "Retry", "Ignore");
//alert(answer);
if(answer==="Abort"){
alert("You selected Abort");
}
else if(answer==="Retry"){
alert("You selected Retry");
}
else if(answer==="Ignore"){
alert("You selected Ignore");
}
Above works perfectly:
var answer = CustomConfirm("Select A Button:", undefined, 2, undefined, "Abort", "Retry", "Ignore");
switch(answer){
Case "Abort"
alert("You selected Abort")
break;
Case "Retry"
alert("You selected Retry")
break;
Case "Ignore"
alert("You selected Ignore")
break;
}
Above does nothing, not sure why ...
if(CustomConfirm("Select A Button:", undefined, 2, undefined, "Abort", "Retry", "Ignore")==="Abort"){
alert("You selected Abort");
}
else if(CustomConfirm("Select A Button:", undefined, 2, undefined, "Abort", "Retry", "Ignore")==="Retry"){
alert("You selected Retry");
}
else if(CustomConfirm("Select A Button:", undefined, 2, undefined, "Abort", "Retry", "Ignore")==="Ignore"){
alert("You selected Ignore");
}
Above is awkward. If you are clicking Button 3, you have to click it three times (the pop-up reappears) and then it works.
To Do:
Copy link to clipboard
Copied
Fixed it. Final code (it could be prettier/more efficient, but it works):
function CustomConfirm(message, title, DefaultBtn, Btn1Text, Btn2Text, Btn3Text, Btn4Text, bgcolor) {
// Yes/No, OKOnly, OK/Cancel, Abort/Retry/Ignore, Yes/No/Cancel, Retry/Ignore,
title = title || "Script Alert";
Btn1Text = Btn1Text || "";
Btn2Text = Btn2Text || "";
Btn3Text = Btn3Text || "";
Btn4Text = Btn4Text || "";
DefaulBtn = DefaultBtn || 0;
// Shift the buttons:
if (Btn1Text===""){
// Show at least one button
Btn4Text="OK";
}
else if (Btn2Text===""){
// Only one button
Btn4Text=Btn1Text;
Btn1Text = "";
if (DefaultBtn===1){
DefaultBtn=4;
}
}
else if (Btn3Text===""){
// Two Buttons
Btn4Text=Btn2Text;
Btn3Text=Btn1Text;
Btn2Text = "";
Btn1Text = "";
if (DefaultBtn===1){
DefaultBtn=3;
}
else if (DefaultBtn===2){
DefaultBtn=4
}
}
else if (Btn4Text===""){
// Three Buttons
Btn4Text=Btn3Text;
Btn3Text=Btn2Text;
Btn2Text = Btn1Text;
Btn1Text = "";
if (DefaultBtn===1){
DefaultBtn=2;
}
else if (DefaultBtn===2){
DefaultBtn=3;
}
else if (DefaultBtn===3){
DefaultBtn=4;
}
}
bgcolor = bgcolor || "gray";
var result = "";
var win = new Window("dialog", title, undefined, {closeButton:false});
win.orientation = "column";
win.alignChildren = "left";
if(bgcolor==="white"){
win.graphics.backgroundColor = win.graphics.newBrush (win.graphics.BrushType.SOLID_COLOR, [1.0, 1.0, 1.0]);
}
var msg = win.add("statictext", undefined, message);
var myButtonGroup = win.add ("group");
myButtonGroup.alignment = "right";
var Btn1 = myButtonGroup.add ("button", undefined, Btn1Text);
if(Btn1Text===""){
Btn1.visible=false;
}
var Btn2 = myButtonGroup.add ("button", undefined, Btn2Text);
if(Btn2Text===""){
Btn2.visible=false;
}
var Btn3 = myButtonGroup.add ("button", undefined, Btn3Text);
if(Btn3Text===""){
Btn3.visible=false;
}
var Btn4 = myButtonGroup.add ("button", undefined, Btn4Text);
if(Btn4Text===""){
Btn4.visible=false;
}
switch(DefaultBtn){
case 1:
win.defaultElement=Btn1;
break;
case 2:
win.defaultElement=Btn2;
break;
case 3:
win.defaultElement=Btn3;
break;
case 4:
win.defaultElement=Btn4;
}
// Event Listeners
Btn1.onClick=function(){
result = Btn1Text;
win.close();
return result;
};
Btn2.onClick=function(){
result = Btn2Text;
win.close();
return result;
};
Btn3.onClick=function(){
result = Btn3Text;
win.close();
return result;
};
Btn4.onClick=function(){
result = Btn4Text;
win.close();
return result;
}
// Show the window
set_font (win, "Tahoma:14");
win.show();
return result;
} // End CustomConfirm
Calling Code (I'm not sure why switch doesn't work, but ...):
var answer = CustomConfirm("Select A Button:", undefined, 2, "Retry", "Ignore");
// Include up to 4 buttons in the order you want them to appear. Set Default Button to 0 if you don't want a default.
if(answer==="Retry"){
alert("You selected Retry");
}
else if(answer==="Ignore"){
alert("You selected Ignore");
}
Alernative (simpler) calling statement:
switch(CustomConfirm("Select A Button:", undefined, 2, "Abort", "Retry", "Ignore")){
// Include up to 4 buttons in the order you want them to appear. Set Default Button to 0 if you don't want a default.
case "Abort":
alert("You selected Abort")
break;
case "Retry":
alert("You selected Retry")
break;
case "Ignore":
alert("You selected Ignore")
}
Advantages over standard Confirm dialog (or even VBA Enhanced Message Box):
Disadvantage:
Copy link to clipboard
Copied
Minor edits above. "case 4" didn't need a break statement since it was the last statement, but it didn't hurt anything. In the calling statement, "case" needed to be lower-case instead of initial caps, and I was missing the ":" at the end of the statement.
Copy link to clipboard
Copied
Updated the scripts to auto-size and or wrap correctly with the help of this thread: https://community.adobe.com/t5/indesign-discussions/script-ui-dynamically-autosizing-statictext/td-p...
EDIT: Had to make a minor change to the "if" statement in AutocloseAlert(). The previous version would fail (only display the first line) if message length was < 80 and you have manual line feeds, e.g.:
AutocloseAlert("Line 1\rLine2");
EDIT2: Had to correct the "if" statement, not found returns -1, not 0.
Here are the final (I hope) versions:
function AutocloseAlert(message, delaySeconds, title, bgcolor) {
title = title || "Script Alert";
delaySeconds = delaySeconds || 0
bgcolor = bgcolor || "gray";
if(delaySeconds===0){
var win = new Window("dialog", title, undefined, {closeButton:false});
}
else{
var win = new Window("palette", title, undefined, {closeButton:false});
}
win.margins = 10;
win.orientation = "column";
win.alignChildren = "center";
if(bgcolor==="white"){
win.graphics.backgroundColor = win.graphics.newBrush (win.graphics.BrushType.SOLID_COLOR, [1.0, 1.0, 1.0]);
}
// Dialog Width To Be Defined:
var w_width = 450;
// 80 below is somewhat arbitrary. Run the script and see where the first line ends. Adjust w_static text to a bit longer than that. Uncomment the line below to get the text length, Use that in the "if" statement.
//alert (message.length)
if (message.length < 80 && message.indexOf("\r")===-1 && message.indexOf("\n")===-1) {
// single line
var msg = win.add('statictext', undefined, message);
}
else{
// multiline
var msg = win.add('statictext', undefined, 'X', {multiline: true});
// if not using standard font size, Font must be defined below, even if using set_font, or the message will truncate unpredictably.
msg.graphics.font="Tahoma:14";
var X_width = msg.preferredSize[0];
with(msg){preferredSize = [-1,-1]; characters = ~~(w_width/X_width); preferredSize[1] = -1;};
msg.text = message;
}
if (delaySeconds>0){
var btn = win.add("button", undefined, "OK (" + delaySeconds + ")");
}
else{
var btn = win.add("button", undefined, "OK",{name: "ok"});
}
var cancelled = false;
// Function for button click
btn.onClick = function () {
cancelled = true;
win.close();
$.writeln("User clicked OK");
};
// Show the window
set_font (win, "Tahoma:14");
win.show();
if (delaySeconds>0){
// Countdown loop
while (delaySeconds > 0 && !cancelled) {
$.sleep(1000); // wait 1 second
delaySeconds--;
try {
if(delaySeconds > 0){
btn.text = "OK (" + delaySeconds + ")";
}
else {
btn.text = "OK";
}
//win.update(); // Force the window to update
} catch (e) {
break; // window might be closed already
}
}
// Close window after countdown, unless user clicked OK
if (!cancelled) {
win.close();
$.writeln("Auto-closed after timeout");
}
}
} // End AutocloseAlert
function set_font (control, font) {
for (var i = 0; i < control.children.length; i++) {
if ("GroupPanel".indexOf (control.children[i].constructor.name) > -1)
set_font (control.children[i], font);
else
control.children[i].graphics.font = font;
}
}//--end set_font;
function CustomConfirm(message, title, DefaultBtn, Btn1Text, Btn2Text, Btn3Text, Btn4Text, bgcolor) {
// Yes/No, OKOnly, OK/Cancel, Abort/Retry/Ignore, Yes/No/Cancel, Retry/Ignore,
title = title || "Script Alert";
Btn1Text = Btn1Text || "";
Btn2Text = Btn2Text || "";
Btn3Text = Btn3Text || "";
Btn4Text = Btn4Text || "";
DefaulBtn = DefaultBtn || 0;
// Shift the buttons:
if (Btn1Text===""){
// Show at least one button
Btn4Text="OK";
}
else if (Btn2Text===""){
// Only one button
Btn4Text=Btn1Text;
Btn1Text = "";
if (DefaultBtn===1){
DefaultBtn=4;
}
}
else if (Btn3Text===""){
// Two Buttons
Btn4Text=Btn2Text;
Btn3Text=Btn1Text;
Btn2Text = "";
Btn1Text = "";
if (DefaultBtn===1){
DefaultBtn=3;
}
else if (DefaultBtn===2){
DefaultBtn=4
}
}
else if (Btn4Text===""){
// Three Buttons
Btn4Text=Btn3Text;
Btn3Text=Btn2Text;
Btn2Text = Btn1Text;
Btn1Text = "";
if (DefaultBtn===1){
DefaultBtn=2;
}
else if (DefaultBtn===2){
DefaultBtn=3;
}
else if (DefaultBtn===3){
DefaultBtn=4;
}
}
bgcolor = bgcolor || "gray";
var result = "";
var win = new Window("dialog", title, undefined, {closeButton:false});
win.margins = 10;
win.orientation = "column";
win.alignChildren = "left";
if(bgcolor==="white"){
win.graphics.backgroundColor = win.graphics.newBrush (win.graphics.BrushType.SOLID_COLOR, [1.0, 1.0, 1.0]);
}
// Dialog Width to be defined:
// If using Tahoma:14, there is no reason to set w_width below 350. Min Width is determined by the 4 buttons, even if some are not visible. Values over 350 make the window wider. I like 450.
var w_width = 450;
var msg = win.add("statictext", undefined, 'X', {multiline: true});
// Must be set here or some of the message gets chopped off.
msg.graphics.font="Tahoma:14";
var X_width = msg.preferredSize[0];
with (msg){preferredSize = [-1,-1]; characters = ~~(w_width/X_width); preferredSize[1] = -1;};
msg.text=message
var myButtonGroup = win.add ("group");
myButtonGroup.alignment = "right";
var Btn1 = myButtonGroup.add ("button", undefined, Btn1Text);
if(Btn1Text===""){
Btn1.visible=false;
}
var Btn2 = myButtonGroup.add ("button", undefined, Btn2Text);
if(Btn2Text===""){
Btn2.visible=false;
}
var Btn3 = myButtonGroup.add ("button", undefined, Btn3Text);
if(Btn3Text===""){
Btn3.visible=false;
}
var Btn4 = myButtonGroup.add ("button", undefined, Btn4Text);
if(Btn4Text===""){
Btn4.visible=false;
}
switch(DefaultBtn){
case 1:
win.defaultElement=Btn1;
break;
case 2:
win.defaultElement=Btn2;
break;
case 3:
win.defaultElement=Btn3;
break;
case 4:
win.defaultElement=Btn4;
}
// Event Listeners
Btn1.onClick=function(){
result = Btn1Text;
win.close();
return result;
};
Btn2.onClick=function(){
result = Btn2Text;
win.close();
return result;
};
Btn3.onClick=function(){
result = Btn3Text;
win.close();
return result;
};
Btn4.onClick=function(){
result = Btn4Text;
win.close();
return result;
}
// Show the window
set_font (win, "Tahoma:14");
win.show();
return result;
} // End CustomConfirm
// Calling functions:
AutocloseAlert("This short message will close in 5 seconds.", 5, "Autoclose Alert");
AutocloseAlert("This much longer message will wrap nicely and will stay open until you click the OK button");
switch(CustomConfirm("Super long text, just a test, FWIW. No need to panic. Just see what happens. Go with the flow ... \r\rThis is Line2", undefined, 2, "Abort", "Retry", "Ignore")){
case "Abort":
alert("You selected Abort")
break;
case "Retry":
alert("You selected Retry")
break;
case "Ignore":
alert("You selected Ignore")
}