0

Got another "should-be-easy" problem. I've got a ScriptUI window in which I need to check to make sure all of the fields are filled. The idea is that, when the user clicks the "OK" button, the script checks to make sure the fields are filled in. If not, then it should alert the user to do so and show that same window again until they do fill it all out. Here's what I have so far:

var windowTitle = "Output Script v1.00 by Chris McGee";
var curDate = new Date();
var curDay = curDate.getDate();
var curMonth = curDate.getMonth() + 1;
var curYear = curDate.getYear() - 100;
var dateFormat = /^(0?[1-9]|1[012])[- \/.](0?[1-9]|[12][0-9]|3[01])[- \/.]\d\d$/;

var outputData = new Window("dialog", windowTitle);
    outputData.preferredSize = [337, 286];
    outputData.orientation = "stack";
    outputData.margins = 0;
    var stackGroup = outputData.add("group");
        stackGroup.margins = [0, 55, 0, 0];
        stackGroup.alignment = ["", "top"];
        stackGroup.alignChildren = ["", "top"];
        var textPanel = stackGroup.add("panel");
            textPanel.orientation = "row";
            textPanel.alignChildren = ["", "bottom"];
            var staticGroup = textPanel.add("group");
                staticGroup.orientation = "column";
                staticGroup.alignChildren = "right";
                staticGroup.spacing = 16;
                staticGroup.add("statictext", undefined, "&Order Number:");
                staticGroup.add("statictext", undefined, "&Ship Date:");
                staticGroup.add("statictext", undefined, "&Initials:");
                staticGroup.add("statictext", undefined, "Ove&rruns?");
            var editGroup = textPanel.add("group");
                editGroup.orientation = "column";
                editGroup.alignChildren = "left";
                var orderNumText = editGroup.add("edittext");
                    orderNumText.characters = 8;
                    orderNumText.active = true;
                    orderNumText.onChange = function ()
                    {
                        if (!/\b\d{6}\b/.test(orderNumText.text))
                        {
                            // If the entered text does not contain exactly 6 digits.
                            alert("The order number does not appear to conform to a standard order number.\n Please fix and try again.");
                        }
                    }
                var shipDateText = editGroup.add("edittext");
                    shipDateText.characters = 8;
                    shipDateText.onChange = function ()
                    {
                        if (dateFormat.test(shipDateText.text))
                        {
                            var enteredDate = shipDateText.text.match(/\b\d*\b/g);
                            var entMonth = parseInt(enteredDate[0]);
                            var entDay = parseInt(enteredDate[2]);
                            var entYear = parseInt(enteredDate[4]);
                            if (entYear < curYear || entYear > curYear + 1)
                            {
                                // If the entered year is older than the current year, or
                                // if the entered year is two or more years in the future.
                                alert("Invalid date entered.  Please fix.");
                            }
                            else if ((entYear > curYear && curMonth < 12) || entMonth > curMonth + 1)
                            {
                                // If the entered month is more than one month ahead, just verify that it is correct.
                                alert("Please verify that the entered date is correct before proceeding.");
                            }
                            else if ((entMonth < curMonth && curMonth < 12) || (entMonth == curMonth && entDay < curDay))
                            {
                                // If the entered date is within the same month, but on an earlier day, alert the user.
                                alert("Invalid date entered.  Please fix.");
                            }
                        }
                        else
                        {
                            alert("Date format not recognized.  Please try again.\nDate must be in the form of MM/DD/YY.");
                            shipDateText.text = "";
                        }
                    }
                var initialsText = editGroup.add("edittext");
                    initialsText.characters = 3;
                var overRunsBox = editGroup.add("checkbox");
        var buttonGroup = stackGroup.add("group");
            buttonGroup.orientation = "column";
            var okButton = buttonGroup.add("button", undefined, "OK", {name: "ok"});
            buttonGroup.add("button", undefined, "Cancel", {name: "cancel"});

var allFieldsFilled = false;
while (!allFieldsFilled)
{
    // If the user clicked "OK", then the contents get put into variables and the work begins on the document(s).
    if (outputData.show() == 1) {
        if (orderNumText.text == "" || shipDateText.text == "" || initialsText.text == "")
        {
            alert("Please fill out ALL fields.");
        }
        else
        {
            allFieldsFilled = true;
            var orderNum = orderNumText.text;
            var shipDate = shipDateText.text;
            var outputInitials = initialsText.text;
            var overRuns = overRunsBox.value;
        }
    } else {
        // If the user clicked "Cancel".
        exit();
    }
}

The problem is that the window does not re-appear after the alert message. Why doesn't it, and how can I fix this?

EDIT 09/23/2013: I have added code so that it can be run. I have also noticed that the alert window about entering text appears even if the user clicks "Cancel".

EDIT 09/24/2013: I've tried implementing @ariestav's idea, so my code now looks like this:

var outputData = new Window("dialog", windowTitle);
    outputData.preferredSize = [337, 286];
    outputData.orientation = "stack";
    outputData.margins = 0;
    var stackGroup = outputData.add("group");
        stackGroup.margins = [0, 55, 0, 0];
        stackGroup.alignment = ["", "top"];
        stackGroup.alignChildren = ["", "top"];
        var textPanel = stackGroup.add("panel");
            textPanel.orientation = "row";
            textPanel.alignChildren = ["", "bottom"];
            var staticGroup = textPanel.add("group");
                staticGroup.orientation = "column";
                staticGroup.alignChildren = "right";
                staticGroup.spacing = 16;
                staticGroup.graphics.foregroundColor = staticGroup.graphics.newPen(outputData.graphics.PenType.SOLID_COLOR, [1, 1, 1], 1);
                staticGroup.add("statictext", undefined, "&Order Number:");
                staticGroup.add("statictext", undefined, "&Ship Date:");
                staticGroup.add("statictext", undefined, "&Initials:");
                staticGroup.add("statictext", undefined, "Ove&rruns?");
            var editGroup = textPanel.add("group");
                editGroup.orientation = "column";
                editGroup.alignChildren = "left";
                var orderNumText = editGroup.add("edittext");
                    orderNumText.characters = 8;
                    orderNumText.active = true;
                    orderNumText.onChange = function ()
                    {
                        if (!/\b\d{6}\b/.test(orderNumText.text))
                        {
                            // If the entered text does not contain exactly 6 digits.
                            alert("The order number does not appear to conform to a standard order number.\n Please fix and try again.");
                        }
                    }
                var shipDateText = editGroup.add("edittext");
                    shipDateText.characters = 8;
                    shipDateText.onChange = function ()
                    {
                        if (dateFormat.test(shipDateText.text))
                        {
                            var enteredDate = shipDateText.text.match(/\b\d*\b/g);
                            var entMonth = parseInt(enteredDate[0]);
                            var entDay = parseInt(enteredDate[2]);
                            var entYear = parseInt(enteredDate[4]);
                            if (entYear < curYear || entYear > curYear + 1)
                            {
                                // If the entered year is older than the current year, or
                                // if the entered year is two or more years in the future.
                                alert("Invalid date entered.  Please fix.");
                            }
                            else if ((entYear > curYear && curMonth < 12) || entMonth > curMonth + 1)
                            {
                                // If the entered month is more than one month ahead, just verify that it is correct.
                                alert("Please verify that the entered date is correct before proceeding.");
                            }
                            else if ((entMonth < curMonth && curMonth < 12) || (entMonth == curMonth && entDay < curDay))
                            {
                                // If the entered date is within the same month, but on an earlier day, alert the user.
                                alert("Invalid date entered.  Please fix.");
                            }
                        }
                        else
                        {
                            alert("Date format not recognized.  Please try again.\nDate must be in the form of MM/DD/YY.");
                            shipDateText.text = "";
                        }
                    }
                var initialsText = editGroup.add("edittext");
                    initialsText.characters = 3;
                var overRunsBox = editGroup.add("checkbox");
        var buttonGroup = stackGroup.add("group");
            buttonGroup.orientation = "column";
            var okButton = buttonGroup.add("button", undefined, "OK", {name: "ok"});
                okButton.onClick = function ()
                {
                    if (orderNumText.text == "" || shipDateText.text == "" || initialsText.text == "")
                    {
                        alert("Please fill out ALL fields.");
                    }
                    else
                    {
                        outputData.close();
                    }
                }
            var cancelButton = buttonGroup.add("button", undefined, "Cancel", {name: "cancel"});
                cancelButton.onClick = function () {$.writeln("Canceling."); outputData.close(); exit();}

outputData.show();

var orderNum = orderNumText.text;
var shipDate = shipDateText.text;
var outputInitials = initialsText.text;
var overRuns = overRunsBox.value;

However, the Cancel button does not cancel. It just continues with the code. I thought the exit(); directive would have it just quit out of the script completely. What am I doing wrong?

RobC
  • 22,977
  • 20
  • 73
  • 80
Sturm
  • 689
  • 2
  • 23
  • 52
  • can you give some working code? – fabianmoronzirfas Sep 21 '13 at 11:19
  • I think the window disappears because ExtendScript recognizes buttons with the name or label 'OK' as one that dismisses it. Try renaming your OK button, and changing it's label to something like "Accept" and see if your window disappears upon clicking it. – ariestav Sep 21 '13 at 20:19
  • I've just updated the code so it can be run. @ariestav: Tried that, and it didn't work. The window never closes and the alert box never appears. Here's what I want to have happen: If the user does not fill out all fields, then the window should close (optional), an alert box is shown to remind him that he needs to fill out all fields, and then the original window is shown again to give him another chance. – Sturm Sep 23 '13 at 13:13
  • If you want the window to close, and the button's name or text label are NOT set to "OK", then you need to call the .close() method on the window to explicitly close it. So, validate all your fields. If some need editing then display the alert telling the user to do their job. When they click okay, the window will be there. If the fields' data pass validation then do not display the alert, and call the .close() method on the window object. – ariestav Sep 23 '13 at 17:52
  • @ariestav: So, are you suggesting adding an `.onClick()` callback to the OK button, which checks for the validation? And also change the name & label of that button to something other than 'OK' so the callback will work properly? – Sturm Sep 23 '13 at 18:18
  • @sturm Definitely add a handler for a click event, yes. The name can stay the same if you have registered a handler for the ok button's click. – ariestav Sep 23 '13 at 19:37
  • @ariestav: I've added `.onClick()' callbacks to both buttons, but now things are worse. The Cancel button just continues running code instead of exiting out of the script, as it should. – Sturm Sep 24 '13 at 14:12
  • @sturm are you using the .close() method within the cancel handler? In your code, it appears you are using exit(); which is not the same. – ariestav Sep 24 '13 at 16:46
  • @sturm ah, I see you are doing that. does the dialog actually dismiss from the screen? – ariestav Sep 24 '13 at 16:52
  • Yes, the `.close()` method works fine; it definitely dismisses the dialog. However, the `exit()` function doesn't appear to work when the Cancel button is pressed; the script just keeps on running, when I don't want it to. – Sturm Sep 24 '13 at 18:16
  • How do you know it keeps running? What signifies to you that it's running? I'm not sure I've seen exit() used in any of the ExtendScript development I've done. Does the host application just hang? – ariestav Sep 24 '13 at 18:55
  • There is much more code in my program than what you see above. After the Cancel button (or the OK button, if all fields are filled in) is clicked, the rest of the code executes, which involves showing a progress window while some documents are opened, worked on, printed, saved, and closed. InDesign does not hang, it just continues running the rest of the script. If `exit();` is bad programming practice, is there a better way to cancel out of a script if that Cancel button is pressed? – Sturm Sep 24 '13 at 21:15
  • I've decided to go with a different approach. Instead of checking for validity upon a press of the "OK" button, I've decided to have the script check validity whenever each of the fields is filled. Each field has an `.onChange` callback which sets the button's `.enabled` state to `true` if all fields are filled. Otherwise, the button remains disabled (and unclickable). Much more elegant, I think, than a post-check. All that said, I still wouldn't mind hearing a solution to this issue, if anyone has one, just for future reference. – Sturm Sep 30 '13 at 21:11

2 Answers2

0

Remove the exit() inside the onClick and the error goes away:

cancelButton.onClick = function () {$.writeln("Canceling."); outputData.close();}
Justin Putney
  • 752
  • 1
  • 5
  • 16
  • I've actually added more code to this old problem so that it does validation checking before the "OK" button is pressed. It won't even enable that button until all fields are filled in and in the proper formats. I can post it here, if you think it would be beneficial to others. – Sturm Dec 02 '13 at 17:49
  • It's up to you. If you've solved the problem, it would probably be good to post the solution for others. – Justin Putney Dec 02 '13 at 21:24
0

So, the easiest solution to the problem was one that is almost undocumented. It turns out that the .enabled property can be used for (almost) any ScriptUI object. Thus, I could simply keep the OK button disabled until all of the fields passed verification. I needed a separate function for this, but it works flawlessly:

function ifFieldsFilled ()
{
    if (orderNumText.text != "" && shipDateText.text != "" && initialsText.text != "" && dateValid)
    {
        return true;
    }
    else
    {
        return false;
    }
}

var curDate = new Date();
var curDay = curDate.getDate();
var curMonth = curDate.getMonth() + 1;
var curYear = curDate.getYear() - 100;
var dateFormat = /^(0?[1-9]|1[012])[- \/.](0?[1-9]|[12][0-9]|3[01])[- \/.]\d\d$/;
var dateValid = false;

var outputData = new Window("dialog", windowTitle);
    outputData.preferredSize = [337, 300];
    outputData.orientation = "stack";
    outputData.margins = 0;
    var stackGroup = outputData.add("group");
        stackGroup.margins = [0, 48, 0, 0];
        stackGroup.alignment = ["", "top"];
        stackGroup.alignChildren = ["", "top"];
        var textPanel = stackGroup.add("panel");
            textPanel.orientation = "row";
            textPanel.alignChildren = ["", "bottom"];
            var staticGroup = textPanel.add("group");
                staticGroup.orientation = "column";
                staticGroup.alignChildren = "right";
                staticGroup.spacing = 16;
                staticGroup.graphics.foregroundColor = staticGroup.graphics.newPen(outputData.graphics.PenType.SOLID_COLOR, [1, 1, 1], 1);
                staticGroup.add("statictext", undefined, "&Order Number:");
                staticGroup.add("statictext", undefined, "&Ship Date:");
                staticGroup.add("statictext", undefined, "&Initials:");
                staticGroup.add("statictext", undefined, "Ove&rruns?");
                staticGroup.add("statictext", undefined, "Digital &Print?");
            var editGroup = textPanel.add("group");
                editGroup.orientation = "column";
                editGroup.alignChildren = "left";
                var orderNumText = editGroup.add("edittext");
                    orderNumText.characters = 8;
                    orderNumText.active = true;
                    orderNumText.onChange = function ()
                    {
                        if (!/\b\d{6}\b/.test(orderNumText.text) && orderNumText.text != "")
                        {
                            // If the entered text does not contain exactly 6 digits.
                            alert("The order number does not appear to conform to a standard order number.\n Please fix and try again.");
                        }
                        okButton.enabled = ifFieldsFilled();
                    }
                var shipDateText = editGroup.add("edittext");
                    shipDateText.characters = 8;
                    shipDateText.onChange = function ()
                    {
                        if (dateFormat.test(shipDateText.text))
                        {
                            var enteredDate = shipDateText.text.match(/\b\d*\b/g);
                            var entMonth = parseInt(enteredDate[0]);
                            var entDay = parseInt(enteredDate[2]);
                            var entYear = parseInt(enteredDate[4]);
                            if (entYear < curYear || entYear > curYear + 1)
                            {
                                // If the entered year is older than the current year, or
                                // if the entered year is two or more years in the future.
                                alert("Invalid date entered.  Please fix.");
                                dateValid = false;
                            }
                            else if ((entYear > curYear && curMonth < 12) || entMonth > curMonth + 1)
                            {
                                // If the entered month is more than one month ahead, just verify that it is correct.
                                alert("Please verify that the entered date is correct before proceeding.");
                            }
                            else if ((entMonth < curMonth && curMonth < 12) || (entMonth == curMonth && entDay < curDay))
                            {
                                // If the entered date is within the same month, but on an earlier day, alert the user.
                                alert("Invalid date entered.  Please fix.");
                                dateValid = false;
                            }
                            else
                            {
                                // The date is completely valid.
                                dateValid = true;
                            }
                        }
                        else
                        {
                            alert("Date format not recognized.  Please try again.\nDate must be in the form of MM/DD/YY.");
                            shipDateText.text = "";
                        }
                        okButton.enabled = ifFieldsFilled();
                    }
                var initialsText = editGroup.add("edittext");
                    initialsText.characters = 3;
                    initialsText.onChanging = function ()
                    {
                        okButton.enabled = ifFieldsFilled();
                    }
                var overRunsBox = editGroup.add("checkbox");
                var digitalPrintBox = editGroup.add("checkbox");
        var buttonGroup = stackGroup.add("group");
            buttonGroup.orientation = "column";
            var okButton = buttonGroup.add("button", undefined, "OK", {name: "ok"});
                okButton.enabled = false;
            var cancelButton = buttonGroup.add("button", undefined, "Cancel", {name: "cancel"});

// If the user clicked "OK", then the contents get put into variables and the work begins on the document(s).
if (outputData.show() == 1) {
    var orderNum = orderNumText.text;
    var shipDate = shipDateText.text;
    var outputInitials = initialsText.text;
    var overRuns = overRunsBox.value;
    var digitalPrint = digitalPrintBox.value;
} else {
    // If the user clicked "Cancel".
    exit();
}

And the code continues on from there.

So, the okButton starts off as being disabled, then it checks every time the user fills in a field or, in the case of the initialsText field, while the user is typing something. Also, the extra condition && orderNumText.text != "" that was added to the orderNumText's .onChange() function is only there to keep an annoying alert dialog from displaying if the user hits [ESC] or clicks the Cancel button before filling out that text box.

So, that sneaky little .enabled property was the key that helped me solve this problem. Kind of an obvious answer, in retrospect. Regardless, I hope this is helpful to anyone else who was experiencing a problem similar to this one. Take care!

Sturm
  • 689
  • 2
  • 23
  • 52